diff options
Diffstat (limited to 'tests/test_tools/selenium/core/scripts')
21 files changed, 0 insertions, 12216 deletions
diff --git a/tests/test_tools/selenium/core/scripts/find_matching_child.js b/tests/test_tools/selenium/core/scripts/find_matching_child.js deleted file mode 100644 index fbf35b75..00000000 --- a/tests/test_tools/selenium/core/scripts/find_matching_child.js +++ /dev/null @@ -1,69 +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. - * - */ - -elementFindMatchingChildren = function(element, selector) { - var matches = []; - - var childCount = element.childNodes.length; - for (var i=0; i<childCount; i++) { - var child = element.childNodes[i]; - if (selector(child)) { - matches.push(child); - } else { - childMatches = elementFindMatchingChildren(child, selector); - matches.push(childMatches); - } - } - - return matches.flatten(); -} - -ELEMENT_NODE_TYPE = 1; - -elementFindFirstMatchingChild = function(element, selector) { - - var childCount = element.childNodes.length; - for (var i=0; i<childCount; i++) { - var child = element.childNodes[i]; - if (child.nodeType == ELEMENT_NODE_TYPE) { - if (selector(child)) { - return child; - } - result = elementFindFirstMatchingChild(child, selector); - if (result) { - return result; - } - } - } - return null; -} - -elementFindFirstMatchingParent = function(element, selector) { - var current = element.parentNode; - while (current != null) { - if (selector(current)) { - break; - } - current = current.parentNode; - } - return current; -} - -elementFindMatchingChildById = function(element, id) { - return elementFindFirstMatchingChild(element, function(element){return element.id==id} ); -} - 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) -} diff --git a/tests/test_tools/selenium/core/scripts/injection.html b/tests/test_tools/selenium/core/scripts/injection.html deleted file mode 100644 index a75c7211..00000000 --- a/tests/test_tools/selenium/core/scripts/injection.html +++ /dev/null @@ -1,79 +0,0 @@ -<script language="JavaScript"> - if (window["selenium_has_been_loaded_into_this_window"]==null) - { - - __SELENIUM_JS__ - -// Some background on the code below: broadly speaking, where we are relative to other windows -// when running in proxy injection mode depends on whether we are in a frame set file or not. -// -// In regular HTML files, the selenium JavaScript is injected into an iframe called "selenium" -// in order to reduce its impact on the JavaScript environment (through namespace pollution, -// etc.). So in regular HTML files, we need to look at the parent of the current window when we want -// a handle to, e.g., the application window. -// -// In frame set files, we can't use an iframe, so we put the JavaScript in the head element and share -// the window with the frame set. So in this case, we need to look at the current window, not the -// parent when looking for, e.g., the application window. (TODO: Perhaps I should have just -// assigned a regular frame for selenium?) -// -BrowserBot.prototype.getContentWindow = function() { - if (window["seleniumInSameWindow"] != null) return window; - return window.parent; -}; - -BrowserBot.prototype.getTargetWindow = function(windowName) { - if (window["seleniumInSameWindow"] != null) return window; - return window.parent; -}; - -BrowserBot.prototype.getCurrentWindow = function() { - if (window["seleniumInSameWindow"] != null) return window; - return window.parent; -}; - -LOG.openLogWindow = function(message, className) { - // disable for now -}; - -BrowserBot.prototype.relayToRC = function(name) { - var object = eval(name); - var s = 'state:' + serializeObject(name, object) + "\n"; - sendToRC(s,"state=true"); -} - -BrowserBot.prototype.relayBotToRC = function(s) { - this.relayToRC("selenium." + s); -} - -function selenium_frameRunTest(oldOnLoadRoutine) { - if (oldOnLoadRoutine) { - eval(oldOnLoadRoutine); - } - runSeleniumTest(); -} - -function seleniumOnLoad() { - injectedSessionId = @SESSION_ID@; - window["selenium_has_been_loaded_into_this_window"] = true; - runSeleniumTest(); -} - -function seleniumOnUnload() { - sendToRC("OK"); // just in case some poor PI server thread is waiting for a response -} - -if (window.addEventListener) { - window.addEventListener("load", seleniumOnLoad, false); // firefox - window.addEventListener("unload", seleniumOnUnload, false); // firefox -} else if (window.attachEvent){ - window.attachEvent("onload", seleniumOnLoad); // IE - window.attachEvent("onunload", seleniumOnUnload); // IE -} -else { - throw "causing a JavaScript error to tell the world that I did not arrange to be run on load"; -} - -injectedSessionId = @SESSION_ID@; -} -</script> diff --git a/tests/test_tools/selenium/core/scripts/injection_iframe.html b/tests/test_tools/selenium/core/scripts/injection_iframe.html deleted file mode 100644 index bc26e859..00000000 --- a/tests/test_tools/selenium/core/scripts/injection_iframe.html +++ /dev/null @@ -1,7 +0,0 @@ -<script language="JavaScript"> - // Ideally I would avoid polluting the namespace by enclosing this snippet with - // curly braces, but I want to make it easy to look at what URL I used for anyone - // who is interested in looking into http://jira.openqa.org/browse/SRC-101: - var _sel_url_ = "http://" + location.host + "/selenium-server/core/scripts/injection.html"; - document.write('<iframe name="selenium" width=0 height=0 id="selenium" src="' + _sel_url_ + '"></iframe>'); -</script> diff --git a/tests/test_tools/selenium/core/scripts/js2html.js b/tests/test_tools/selenium/core/scripts/js2html.js deleted file mode 100644 index 407709df..00000000 --- a/tests/test_tools/selenium/core/scripts/js2html.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - -This is an experiment in using the Narcissus JavaScript engine -to allow Selenium scripts to be written in plain JavaScript. - -The 'jsparse' function will compile each high level block into a Selenium table script. - - -TODO: -1) Test! (More browsers, more sample scripts) -2) Stepping and walking lower levels of the parse tree -3) Calling Selenium commands directly from JavaScript -4) Do we want comments to appear in the TestRunner? -5) Fix context so variables don't have to be global - For now, variables defined with "var" won't be found - if used later on in a script. -6) Fix formatting -*/ - - -function jsparse() { - var script = document.getElementById('sejs') - var fname = 'javascript script'; - parse_result = parse(script.text, fname, 0); - - var x2 = new ExecutionContext(GLOBAL_CODE); - ExecutionContext.current = x2; - - - var new_test_source = ''; - var new_line = ''; - - for (i=0;i<parse_result.$length;i++){ - var the_start = parse_result[i].start; - var the_end; - if ( i == (parse_result.$length-1)) { - the_end = parse_result.tokenizer.source.length; - } else { - the_end = parse_result[i+1].start; - } - - var script_fragment = parse_result.tokenizer.source.slice(the_start,the_end) - - new_line = '<tr><td style="display:none;" class="js">getEval</td>' + - '<td style="display:none;">currentTest.doNextCommand()</td>' + - '<td style="white-space: pre;">' + script_fragment + '</td>' + - '<td></td></tr>\n'; - new_test_source += new_line; - //eval(script_fragment); - - - }; - - - - execute(parse_result,x2) - - // Create HTML Table - body = document.body - body.innerHTML += "<table class='selenium' id='se-js-table'>"+ - "<tbody>" + - "<tr><td>// " + document.title + "</td></tr>" + - new_test_source + - "</tbody" + - "</table>"; - - //body.innerHTML = "<pre>" + parse_result + "</pre>" -} - - diff --git a/tests/test_tools/selenium/core/scripts/narcissus-defs.js b/tests/test_tools/selenium/core/scripts/narcissus-defs.js deleted file mode 100644 index 5869397d..00000000 --- a/tests/test_tools/selenium/core/scripts/narcissus-defs.js +++ /dev/null @@ -1,175 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (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.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Narcissus JavaScript engine. - * - * The Initial Developer of the Original Code is - * Brendan Eich <brendan@mozilla.org>. - * Portions created by the Initial Developer are Copyright (C) 2004 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Narcissus - JS implemented in JS. - * - * Well-known constants and lookup tables. Many consts are generated from the - * tokens table via eval to minimize redundancy, so consumers must be compiled - * separately to take advantage of the simple switch-case constant propagation - * done by SpiderMonkey. - */ - -// jrh -//module('JS.Defs'); - -GLOBAL = this; - -var tokens = [ - // End of source. - "END", - - // Operators and punctuators. Some pair-wise order matters, e.g. (+, -) - // and (UNARY_PLUS, UNARY_MINUS). - "\n", ";", - ",", - "=", - "?", ":", "CONDITIONAL", - "||", - "&&", - "|", - "^", - "&", - "==", "!=", "===", "!==", - "<", "<=", ">=", ">", - "<<", ">>", ">>>", - "+", "-", - "*", "/", "%", - "!", "~", "UNARY_PLUS", "UNARY_MINUS", - "++", "--", - ".", - "[", "]", - "{", "}", - "(", ")", - - // Nonterminal tree node type codes. - "SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX", - "ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER", - "GROUP", "LIST", - - // Terminals. - "IDENTIFIER", "NUMBER", "STRING", "REGEXP", - - // Keywords. - "break", - "case", "catch", "const", "continue", - "debugger", "default", "delete", "do", - "else", "enum", - "false", "finally", "for", "function", - "if", "in", "instanceof", - "new", "null", - "return", - "switch", - "this", "throw", "true", "try", "typeof", - "var", "void", - "while", "with", - // Extensions - "require", "bless", "mixin", "import" -]; - -// Operator and punctuator mapping from token to tree node type name. -// NB: superstring tokens (e.g., ++) must come before their substring token -// counterparts (+ in the example), so that the opRegExp regular expression -// synthesized from this list makes the longest possible match. -var opTypeNames = { - '\n': "NEWLINE", - ';': "SEMICOLON", - ',': "COMMA", - '?': "HOOK", - ':': "COLON", - '||': "OR", - '&&': "AND", - '|': "BITWISE_OR", - '^': "BITWISE_XOR", - '&': "BITWISE_AND", - '===': "STRICT_EQ", - '==': "EQ", - '=': "ASSIGN", - '!==': "STRICT_NE", - '!=': "NE", - '<<': "LSH", - '<=': "LE", - '<': "LT", - '>>>': "URSH", - '>>': "RSH", - '>=': "GE", - '>': "GT", - '++': "INCREMENT", - '--': "DECREMENT", - '+': "PLUS", - '-': "MINUS", - '*': "MUL", - '/': "DIV", - '%': "MOD", - '!': "NOT", - '~': "BITWISE_NOT", - '.': "DOT", - '[': "LEFT_BRACKET", - ']': "RIGHT_BRACKET", - '{': "LEFT_CURLY", - '}': "RIGHT_CURLY", - '(': "LEFT_PAREN", - ')': "RIGHT_PAREN" -}; - -// Hash of keyword identifier to tokens index. NB: we must null __proto__ to -// avoid toString, etc. namespace pollution. -var keywords = {__proto__: null}; - -// Define const END, etc., based on the token names. Also map name to index. -var consts = " "; -for (var i = 0, j = tokens.length; i < j; i++) { - if (i > 0) - consts += "; "; - var t = tokens[i]; - if (/^[a-z]/.test(t)) { - consts += t.toUpperCase(); - keywords[t] = i; - } else { - consts += (/^\W/.test(t) ? opTypeNames[t] : t); - } - consts += " = " + i; - tokens[t] = i; -} -eval(consts + ";"); - -// Map assignment operators to their indexes in the tokens array. -var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%']; - -for (i = 0, j = assignOps.length; i < j; i++) { - t = assignOps[i]; - assignOps[t] = tokens[t]; -} diff --git a/tests/test_tools/selenium/core/scripts/narcissus-exec.js b/tests/test_tools/selenium/core/scripts/narcissus-exec.js deleted file mode 100644 index e2c88f81..00000000 --- a/tests/test_tools/selenium/core/scripts/narcissus-exec.js +++ /dev/null @@ -1,1054 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * vim: set ts=4 sw=4 et tw=80: - * - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (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.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Narcissus JavaScript engine. - * - * The Initial Developer of the Original Code is - * Brendan Eich <brendan@mozilla.org>. - * Portions created by the Initial Developer are Copyright (C) 2004 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Narcissus - JS implemented in JS. - * - * Execution of parse trees. - * - * Standard classes except for eval, Function, Array, and String are borrowed - * from the host JS environment. Function is metacircular. Array and String - * are reflected via wrapping the corresponding native constructor and adding - * an extra level of prototype-based delegation. - */ - -// jrh -//module('JS.Exec'); -// end jrh - -GLOBAL_CODE = 0; EVAL_CODE = 1; FUNCTION_CODE = 2; - -function ExecutionContext(type) { - this.type = type; -} - -// jrh -var agenda = new Array(); -var skip_setup = 0; -// end jrh - -var global = { - // Value properties. - NaN: NaN, Infinity: Infinity, undefined: undefined, - alert : function(msg) { alert(msg) }, - confirm : function(msg) { return confirm(msg) }, - document : document, - window : window, - // jrh - //debug: window.open('','debugwindow','width=600,height=400,scrollbars=yes,resizable=yes'), - // end jrh - navigator : navigator, - XMLHttpRequest : function() { return new XMLHttpRequest() }, - // Function properties. - eval: function(s) { - if (typeof s != "string") { - return s; - } - - var x = ExecutionContext.current; - var x2 = new ExecutionContext(EVAL_CODE); - x2.thisObject = x.thisObject; - x2.caller = x.caller; - x2.callee = x.callee; - x2.scope = x.scope; - ExecutionContext.current = x2; - try { - execute(parse(s), x2); - } catch (e) { - x.result = x2.result; - throw e; - } finally { - ExecutionContext.current = x; - } - return x2.result; - }, - parseInt: parseInt, parseFloat: parseFloat, - isNaN: isNaN, isFinite: isFinite, - decodeURI: decodeURI, encodeURI: encodeURI, - decodeURIComponent: decodeURIComponent, - encodeURIComponent: encodeURIComponent, - - // Class constructors. Where ECMA-262 requires C.length == 1, we declare - // a dummy formal parameter. - Object: Object, - Function: function(dummy) { - var p = "", b = "", n = arguments.length; - if (n) { - var m = n - 1; - if (m) { - p += arguments[0]; - for (var k = 1; k < m; k++) - p += "," + arguments[k]; - } - b += arguments[m]; - } - - // XXX We want to pass a good file and line to the tokenizer. - // Note the anonymous name to maintain parity with Spidermonkey. - var t = new Tokenizer("anonymous(" + p + ") {" + b + "}"); - - // NB: Use the STATEMENT_FORM constant since we don't want to push this - // function onto the null compilation context. - var f = FunctionDefinition(t, null, false, STATEMENT_FORM); - var s = {object: global, parent: null}; - return new FunctionObject(f, s); - }, - Array: function(dummy) { - // Array when called as a function acts as a constructor. - return GLOBAL.Array.apply(this, arguments); - }, - String: function(s) { - // Called as function or constructor: convert argument to string type. - s = arguments.length ? "" + s : ""; - if (this instanceof String) { - // Called as constructor: save the argument as the string value - // of this String object and return this object. - this.value = s; - return this; - } - return s; - }, - Boolean: Boolean, Number: Number, Date: Date, RegExp: RegExp, - Error: Error, EvalError: EvalError, RangeError: RangeError, - ReferenceError: ReferenceError, SyntaxError: SyntaxError, - TypeError: TypeError, URIError: URIError, - - // Other properties. - Math: Math, - - // Extensions to ECMA. - //snarf: snarf, - evaluate: evaluate, - load: function(s) { - if (typeof s != "string") - return s; - var req = new XMLHttpRequest(); - req.open('GET', s, false); - req.send(null); - - evaluate(req.responseText, s, 1) - }, - print: print, version: null -}; - -// jrh -//global.debug.document.body.innerHTML = '' -// end jrh - -// Helper to avoid Object.prototype.hasOwnProperty polluting scope objects. -function hasDirectProperty(o, p) { - return Object.prototype.hasOwnProperty.call(o, p); -} - -// Reflect a host class into the target global environment by delegation. -function reflectClass(name, proto) { - var gctor = global[name]; - gctor.prototype = proto; - proto.constructor = gctor; - return proto; -} - -// Reflect Array -- note that all Array methods are generic. -reflectClass('Array', new Array); - -// Reflect String, overriding non-generic methods. -var gSp = reflectClass('String', new String); -gSp.toSource = function () { return this.value.toSource(); }; -gSp.toString = function () { return this.value; }; -gSp.valueOf = function () { return this.value; }; -global.String.fromCharCode = String.fromCharCode; - -var XCp = ExecutionContext.prototype; -ExecutionContext.current = XCp.caller = XCp.callee = null; -XCp.scope = {object: global, parent: null}; -XCp.thisObject = global; -XCp.result = undefined; -XCp.target = null; -XCp.ecmaStrictMode = false; - -function Reference(base, propertyName, node) { - this.base = base; - this.propertyName = propertyName; - this.node = node; -} - -Reference.prototype.toString = function () { return this.node.getSource(); } - -function getValue(v) { - if (v instanceof Reference) { - if (!v.base) { - throw new ReferenceError(v.propertyName + " is not defined", - v.node.filename(), v.node.lineno); - } - return v.base[v.propertyName]; - } - return v; -} - -function putValue(v, w, vn) { - if (v instanceof Reference) - return (v.base || global)[v.propertyName] = w; - throw new ReferenceError("Invalid assignment left-hand side", - vn.filename(), vn.lineno); -} - -function isPrimitive(v) { - var t = typeof v; - return (t == "object") ? v === null : t != "function"; -} - -function isObject(v) { - var t = typeof v; - return (t == "object") ? v !== null : t == "function"; -} - -// If r instanceof Reference, v == getValue(r); else v === r. If passed, rn -// is the node whose execute result was r. -function toObject(v, r, rn) { - switch (typeof v) { - case "boolean": - return new global.Boolean(v); - case "number": - return new global.Number(v); - case "string": - return new global.String(v); - case "function": - return v; - case "object": - if (v !== null) - return v; - } - var message = r + " (type " + (typeof v) + ") has no properties"; - throw rn ? new TypeError(message, rn.filename(), rn.lineno) - : new TypeError(message); -} - -function execute(n, x) { - if (!this.new_block) - new_block = new Array(); - //alert (n) - var a, f, i, j, r, s, t, u, v; - switch (n.type) { - case FUNCTION: - if (n.functionForm != DECLARED_FORM) { - if (!n.name || n.functionForm == STATEMENT_FORM) { - v = new FunctionObject(n, x.scope); - if (n.functionForm == STATEMENT_FORM) - x.scope.object[n.name] = v; - } else { - t = new Object; - x.scope = {object: t, parent: x.scope}; - try { - v = new FunctionObject(n, x.scope); - t[n.name] = v; - } finally { - x.scope = x.scope.parent; - } - } - } - break; - - case SCRIPT: - t = x.scope.object; - a = n.funDecls; - for (i = 0, j = a.length; i < j; i++) { - s = a[i].name; - f = new FunctionObject(a[i], x.scope); - t[s] = f; - } - a = n.varDecls; - for (i = 0, j = a.length; i < j; i++) { - u = a[i]; - s = u.name; - if (u.readOnly && hasDirectProperty(t, s)) { - throw new TypeError("Redeclaration of const " + s, - u.filename(), u.lineno); - } - if (u.readOnly || !hasDirectProperty(t, s)) { - t[s] = null; - } - } - // FALL THROUGH - - case BLOCK: - for (i = 0, j = n.$length; i < j; i++) { - //jrh - //execute(n[i], x); - //new_block.unshift([n[i], x]); - new_block.push([n[i], x]); - } - new_block.reverse(); - agenda = agenda.concat(new_block); - //agenda = new_block.concat(agenda) - // end jrh - break; - - case IF: - if (getValue(execute(n.condition, x))) - execute(n.thenPart, x); - else if (n.elsePart) - execute(n.elsePart, x); - break; - - case SWITCH: - s = getValue(execute(n.discriminant, x)); - a = n.cases; - var matchDefault = false; - switch_loop: - for (i = 0, j = a.length; ; i++) { - if (i == j) { - if (n.defaultIndex >= 0) { - i = n.defaultIndex - 1; // no case matched, do default - matchDefault = true; - continue; - } - break; // no default, exit switch_loop - } - t = a[i]; // next case (might be default!) - if (t.type == CASE) { - u = getValue(execute(t.caseLabel, x)); - } else { - if (!matchDefault) // not defaulting, skip for now - continue; - u = s; // force match to do default - } - if (u === s) { - for (;;) { // this loop exits switch_loop - if (t.statements.length) { - try { - execute(t.statements, x); - } catch (e) { - if (!(e == BREAK && x.target == n)) { throw e } - break switch_loop; - } - } - if (++i == j) - break switch_loop; - t = a[i]; - } - // NOT REACHED - } - } - break; - - case FOR: - // jrh - // added "skip_setup" so initialization doesn't get called - // on every call.. - if (!skip_setup) - n.setup && getValue(execute(n.setup, x)); - // FALL THROUGH - case WHILE: - // jrh - //while (!n.condition || getValue(execute(n.condition, x))) { - if (!n.condition || getValue(execute(n.condition, x))) { - try { - // jrh - //execute(n.body, x); - new_block.push([n.body, x]); - agenda.push([n.body, x]) - //agenda.unshift([n.body, x]) - // end jrh - } catch (e) { - if (e == BREAK && x.target == n) { - break; - } else if (e == CONTINUE && x.target == n) { - // jrh - // 'continue' is invalid inside an 'if' clause - // I don't know what commenting this out will break! - //continue; - // end jrh - - } else { - throw e; - } - } - n.update && getValue(execute(n.update, x)); - // jrh - new_block.unshift([n, x]) - agenda.splice(agenda.length-1,0,[n, x]) - //agenda.splice(1,0,[n, x]) - skip_setup = 1 - // end jrh - } else { - skip_setup = 0 - } - - break; - - case FOR_IN: - u = n.varDecl; - if (u) - execute(u, x); - r = n.iterator; - s = execute(n.object, x); - v = getValue(s); - - // ECMA deviation to track extant browser JS implementation behavior. - t = (v == null && !x.ecmaStrictMode) ? v : toObject(v, s, n.object); - a = []; - for (i in t) - a.push(i); - for (i = 0, j = a.length; i < j; i++) { - putValue(execute(r, x), a[i], r); - try { - execute(n.body, x); - } catch (e) { - if (e == BREAK && x.target == n) { - break; - } else if (e == CONTINUE && x.target == n) { - continue; - } else { - throw e; - } - } - } - break; - - case DO: - do { - try { - execute(n.body, x); - } catch (e) { - if (e == BREAK && x.target == n) { - break; - } else if (e == CONTINUE && x.target == n) { - continue; - } else { - throw e; - } - } - } while (getValue(execute(n.condition, x))); - break; - - case BREAK: - case CONTINUE: - x.target = n.target; - throw n.type; - - case TRY: - try { - execute(n.tryBlock, x); - } catch (e) { - if (!(e == THROW && (j = n.catchClauses.length))) { - throw e; - } - e = x.result; - x.result = undefined; - for (i = 0; ; i++) { - if (i == j) { - x.result = e; - throw THROW; - } - t = n.catchClauses[i]; - x.scope = {object: {}, parent: x.scope}; - x.scope.object[t.varName] = e; - try { - if (t.guard && !getValue(execute(t.guard, x))) - continue; - execute(t.block, x); - break; - } finally { - x.scope = x.scope.parent; - } - } - } finally { - if (n.finallyBlock) - execute(n.finallyBlock, x); - } - break; - - case THROW: - x.result = getValue(execute(n.exception, x)); - throw THROW; - - case RETURN: - x.result = getValue(execute(n.value, x)); - throw RETURN; - - case WITH: - r = execute(n.object, x); - t = toObject(getValue(r), r, n.object); - x.scope = {object: t, parent: x.scope}; - try { - execute(n.body, x); - } finally { - x.scope = x.scope.parent; - } - break; - - case VAR: - case CONST: - for (i = 0, j = n.$length; i < j; i++) { - u = n[i].initializer; - if (!u) - continue; - t = n[i].name; - for (s = x.scope; s; s = s.parent) { - if (hasDirectProperty(s.object, t)) - break; - } - u = getValue(execute(u, x)); - if (n.type == CONST) - s.object[t] = u; - else - s.object[t] = u; - } - break; - - case DEBUGGER: - throw "NYI: " + tokens[n.type]; - - case REQUIRE: - var req = new XMLHttpRequest(); - req.open('GET', n.filename, 'false'); - - case SEMICOLON: - if (n.expression) - // print debugging statements - - var the_start = n.start - var the_end = n.end - var the_statement = parse_result.tokenizer.source.slice(the_start,the_end) - //global.debug.document.body.innerHTML += ('<pre>>>> <b>' + the_statement + '</b></pre>') - LOG.info('>>>' + the_statement) - x.result = getValue(execute(n.expression, x)); - //if (x.result) - //global.debug.document.body.innerHTML += ( '<pre>>>> ' + x.result + '</pre>') - - break; - - case LABEL: - try { - execute(n.statement, x); - } catch (e) { - if (!(e == BREAK && x.target == n)) { throw e } - } - break; - - case COMMA: - for (i = 0, j = n.$length; i < j; i++) - v = getValue(execute(n[i], x)); - break; - - case ASSIGN: - r = execute(n[0], x); - t = n[0].assignOp; - if (t) - u = getValue(r); - v = getValue(execute(n[1], x)); - if (t) { - switch (t) { - case BITWISE_OR: v = u | v; break; - case BITWISE_XOR: v = u ^ v; break; - case BITWISE_AND: v = u & v; break; - case LSH: v = u << v; break; - case RSH: v = u >> v; break; - case URSH: v = u >>> v; break; - case PLUS: v = u + v; break; - case MINUS: v = u - v; break; - case MUL: v = u * v; break; - case DIV: v = u / v; break; - case MOD: v = u % v; break; - } - } - putValue(r, v, n[0]); - break; - - case CONDITIONAL: - v = getValue(execute(n[0], x)) ? getValue(execute(n[1], x)) - : getValue(execute(n[2], x)); - break; - - case OR: - v = getValue(execute(n[0], x)) || getValue(execute(n[1], x)); - break; - - case AND: - v = getValue(execute(n[0], x)) && getValue(execute(n[1], x)); - break; - - case BITWISE_OR: - v = getValue(execute(n[0], x)) | getValue(execute(n[1], x)); - break; - - case BITWISE_XOR: - v = getValue(execute(n[0], x)) ^ getValue(execute(n[1], x)); - break; - - case BITWISE_AND: - v = getValue(execute(n[0], x)) & getValue(execute(n[1], x)); - break; - - case EQ: - v = getValue(execute(n[0], x)) == getValue(execute(n[1], x)); - break; - - case NE: - v = getValue(execute(n[0], x)) != getValue(execute(n[1], x)); - break; - - case STRICT_EQ: - v = getValue(execute(n[0], x)) === getValue(execute(n[1], x)); - break; - - case STRICT_NE: - v = getValue(execute(n[0], x)) !== getValue(execute(n[1], x)); - break; - - case LT: - v = getValue(execute(n[0], x)) < getValue(execute(n[1], x)); - break; - - case LE: - v = getValue(execute(n[0], x)) <= getValue(execute(n[1], x)); - break; - - case GE: - v = getValue(execute(n[0], x)) >= getValue(execute(n[1], x)); - break; - - case GT: - v = getValue(execute(n[0], x)) > getValue(execute(n[1], x)); - break; - - case IN: - v = getValue(execute(n[0], x)) in getValue(execute(n[1], x)); - break; - - case INSTANCEOF: - t = getValue(execute(n[0], x)); - u = getValue(execute(n[1], x)); - if (isObject(u) && typeof u.__hasInstance__ == "function") - v = u.__hasInstance__(t); - else - v = t instanceof u; - break; - - case LSH: - v = getValue(execute(n[0], x)) << getValue(execute(n[1], x)); - break; - - case RSH: - v = getValue(execute(n[0], x)) >> getValue(execute(n[1], x)); - break; - - case URSH: - v = getValue(execute(n[0], x)) >>> getValue(execute(n[1], x)); - break; - - case PLUS: - v = getValue(execute(n[0], x)) + getValue(execute(n[1], x)); - break; - - case MINUS: - v = getValue(execute(n[0], x)) - getValue(execute(n[1], x)); - break; - - case MUL: - v = getValue(execute(n[0], x)) * getValue(execute(n[1], x)); - break; - - case DIV: - v = getValue(execute(n[0], x)) / getValue(execute(n[1], x)); - break; - - case MOD: - v = getValue(execute(n[0], x)) % getValue(execute(n[1], x)); - break; - - case DELETE: - t = execute(n[0], x); - v = !(t instanceof Reference) || delete t.base[t.propertyName]; - break; - - case VOID: - getValue(execute(n[0], x)); - break; - - case TYPEOF: - t = execute(n[0], x); - if (t instanceof Reference) - t = t.base ? t.base[t.propertyName] : undefined; - v = typeof t; - break; - - case NOT: - v = !getValue(execute(n[0], x)); - break; - - case BITWISE_NOT: - v = ~getValue(execute(n[0], x)); - break; - - case UNARY_PLUS: - v = +getValue(execute(n[0], x)); - break; - - case UNARY_MINUS: - v = -getValue(execute(n[0], x)); - break; - - case INCREMENT: - case DECREMENT: - t = execute(n[0], x); - u = Number(getValue(t)); - if (n.postfix) - v = u; - putValue(t, (n.type == INCREMENT) ? ++u : --u, n[0]); - if (!n.postfix) - v = u; - break; - - case DOT: - r = execute(n[0], x); - t = getValue(r); - u = n[1].value; - v = new Reference(toObject(t, r, n[0]), u, n); - break; - - case INDEX: - r = execute(n[0], x); - t = getValue(r); - u = getValue(execute(n[1], x)); - v = new Reference(toObject(t, r, n[0]), String(u), n); - break; - - case LIST: - // Curse ECMA for specifying that arguments is not an Array object! - v = {}; - for (i = 0, j = n.$length; i < j; i++) { - u = getValue(execute(n[i], x)); - v[i] = u; - } - v.length = i; - break; - - case CALL: - r = execute(n[0], x); - a = execute(n[1], x); - f = getValue(r); - if (isPrimitive(f) || typeof f.__call__ != "function") { - throw new TypeError(r + " is not callable", - n[0].filename(), n[0].lineno); - } - t = (r instanceof Reference) ? r.base : null; - if (t instanceof Activation) - t = null; - v = f.__call__(t, a, x); - break; - - case NEW: - case NEW_WITH_ARGS: - r = execute(n[0], x); - f = getValue(r); - if (n.type == NEW) { - a = {}; - a.length = 0; - } else { - a = execute(n[1], x); - } - if (isPrimitive(f) || typeof f.__construct__ != "function") { - throw new TypeError(r + " is not a constructor", - n[0].filename(), n[0].lineno); - } - v = f.__construct__(a, x); - break; - - case ARRAY_INIT: - v = []; - for (i = 0, j = n.$length; i < j; i++) { - if (n[i]) - v[i] = getValue(execute(n[i], x)); - } - v.length = j; - break; - - case OBJECT_INIT: - v = {}; - for (i = 0, j = n.$length; i < j; i++) { - t = n[i]; - if (t.type == PROPERTY_INIT) { - v[t[0].value] = getValue(execute(t[1], x)); - } else { - f = new FunctionObject(t, x.scope); - /* - u = (t.type == GETTER) ? '__defineGetter__' - : '__defineSetter__'; - v[u](t.name, thunk(f, x)); - */ - } - } - break; - - case NULL: - v = null; - break; - - case THIS: - v = x.thisObject; - break; - - case TRUE: - v = true; - break; - - case FALSE: - v = false; - break; - - case IDENTIFIER: - for (s = x.scope; s; s = s.parent) { - if (n.value in s.object) - break; - } - v = new Reference(s && s.object, n.value, n); - break; - - case NUMBER: - case STRING: - case REGEXP: - v = n.value; - break; - - case GROUP: - v = execute(n[0], x); - break; - - default: - throw "PANIC: unknown operation " + n.type + ": " + uneval(n); - } - return v; -} - -function Activation(f, a) { - for (var i = 0, j = f.params.length; i < j; i++) - this[f.params[i]] = a[i]; - this.arguments = a; -} - -// Null Activation.prototype's proto slot so that Object.prototype.* does not -// pollute the scope of heavyweight functions. Also delete its 'constructor' -// property so that it doesn't pollute function scopes. - -Activation.prototype.__proto__ = null; -delete Activation.prototype.constructor; - -function FunctionObject(node, scope) { - this.node = node; - this.scope = scope; - this.length = node.params.length; - var proto = {}; - this.prototype = proto; - proto.constructor = this; -} - -var FOp = FunctionObject.prototype = { - // Internal methods. - __call__: function (t, a, x) { - var x2 = new ExecutionContext(FUNCTION_CODE); - x2.thisObject = t || global; - x2.caller = x; - x2.callee = this; - a.callee = this; - var f = this.node; - x2.scope = {object: new Activation(f, a), parent: this.scope}; - - ExecutionContext.current = x2; - try { - execute(f.body, x2); - } catch (e) { - if (!(e == RETURN)) { throw e } else if (e == RETURN) { - return x2.result; - } - if (e != THROW) { throw e } - x.result = x2.result; - throw THROW; - } finally { - ExecutionContext.current = x; - } - return undefined; - }, - - __construct__: function (a, x) { - var o = new Object; - var p = this.prototype; - if (isObject(p)) - o.__proto__ = p; - // else o.__proto__ defaulted to Object.prototype - - var v = this.__call__(o, a, x); - if (isObject(v)) - return v; - return o; - }, - - __hasInstance__: function (v) { - if (isPrimitive(v)) - return false; - var p = this.prototype; - if (isPrimitive(p)) { - throw new TypeError("'prototype' property is not an object", - this.node.filename(), this.node.lineno); - } - var o; - while ((o = v.__proto__)) { - if (o == p) - return true; - v = o; - } - return false; - }, - - // Standard methods. - toString: function () { - return this.node.getSource(); - }, - - apply: function (t, a) { - // Curse ECMA again! - if (typeof this.__call__ != "function") { - throw new TypeError("Function.prototype.apply called on" + - " uncallable object"); - } - - if (t === undefined || t === null) - t = global; - else if (typeof t != "object") - t = toObject(t, t); - - if (a === undefined || a === null) { - a = {}; - a.length = 0; - } else if (a instanceof Array) { - var v = {}; - for (var i = 0, j = a.length; i < j; i++) - v[i] = a[i]; - v.length = i; - a = v; - } else if (!(a instanceof Object)) { - // XXX check for a non-arguments object - throw new TypeError("Second argument to Function.prototype.apply" + - " must be an array or arguments object", - this.node.filename(), this.node.lineno); - } - - return this.__call__(t, a, ExecutionContext.current); - }, - - call: function (t) { - // Curse ECMA a third time! - var a = Array.prototype.splice.call(arguments, 1); - return this.apply(t, a); - } -}; - -// Connect Function.prototype and Function.prototype.constructor in global. -reflectClass('Function', FOp); - -// Help native and host-scripted functions be like FunctionObjects. -var Fp = Function.prototype; -var REp = RegExp.prototype; - -if (!('__call__' in Fp)) { - Fp.__call__ = function (t, a, x) { - // Curse ECMA yet again! - a = Array.prototype.splice.call(a, 0, a.length); - return this.apply(t, a); - }; - - REp.__call__ = function (t, a, x) { - a = Array.prototype.splice.call(a, 0, a.length); - return this.exec.apply(this, a); - }; - - Fp.__construct__ = function (a, x) { - switch (a.length) { - case 0: - return new this(); - case 1: - return new this(a[0]); - case 2: - return new this(a[0], a[1]); - case 3: - return new this(a[0], a[1], a[2]); - case 4: - return new this(a[0], a[1], a[2], a[3]); - case 5: - return new this(a[0], a[1], a[2], a[3], a[4]); - case 6: - return new this(a[0], a[1], a[2], a[3], a[4], a[5]); - case 7: - return new this(a[0], a[1], a[2], a[3], a[4], a[5], a[6]); - } - throw "PANIC: too many arguments to constructor"; - } - - // Since we use native functions such as Date along with host ones such - // as global.eval, we want both to be considered instances of the native - // Function constructor. - Fp.__hasInstance__ = function (v) { - return v instanceof Function || v instanceof global.Function; - }; -} - -function thunk(f, x) { - return function () { return f.__call__(this, arguments, x); }; -} - -function evaluate(s, f, l) { - if (typeof s != "string") - return s; - - var x = ExecutionContext.current; - var x2 = new ExecutionContext(GLOBAL_CODE); - ExecutionContext.current = x2; - try { - execute(parse(s, f, l), x2); - } catch (e) { - if (e != THROW) { throw e } - if (x) { - x.result = x2.result; - throw(THROW); - } - throw x2.result; - } finally { - ExecutionContext.current = x; - } - return x2.result; -} diff --git a/tests/test_tools/selenium/core/scripts/narcissus-parse.js b/tests/test_tools/selenium/core/scripts/narcissus-parse.js deleted file mode 100644 index d6acb836..00000000 --- a/tests/test_tools/selenium/core/scripts/narcissus-parse.js +++ /dev/null @@ -1,1003 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (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.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Narcissus JavaScript engine. - * - * The Initial Developer of the Original Code is - * Brendan Eich <brendan@mozilla.org>. - * Portions created by the Initial Developer are Copyright (C) 2004 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): Richard Hundt <www.plextk.org> - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - * Narcissus - JS implemented in JS. - * - * Lexical scanner and parser. - */ - -// jrh -//module('JS.Parse'); - -// Build a regexp that recognizes operators and punctuators (except newline). -var opRegExp = -/^;|^,|^\?|^:|^\|\||^\&\&|^\||^\^|^\&|^===|^==|^=|^!==|^!=|^<<|^<=|^<|^>>>|^>>|^>=|^>|^\+\+|^\-\-|^\+|^\-|^\*|^\/|^%|^!|^~|^\.|^\[|^\]|^\{|^\}|^\(|^\)/; - -// A regexp to match floating point literals (but not integer literals). -var fpRegExp = /^\d+\.\d*(?:[eE][-+]?\d+)?|^\d+(?:\.\d*)?[eE][-+]?\d+|^\.\d+(?:[eE][-+]?\d+)?/; - -function Tokenizer(s, f, l) { - this.cursor = 0; - this.source = String(s); - this.tokens = []; - this.tokenIndex = 0; - this.lookahead = 0; - this.scanNewlines = false; - this.scanOperand = true; - this.filename = f || ""; - this.lineno = l || 1; -} - -Tokenizer.prototype = { - input : function() { - return this.source.substring(this.cursor); - }, - - done : function() { - return this.peek() == END; - }, - - token : function() { - return this.tokens[this.tokenIndex]; - }, - - match: function (tt) { - return this.get() == tt || this.unget(); - }, - - mustMatch: function (tt) { - if (!this.match(tt)) - throw this.newSyntaxError("Missing " + this.tokens[tt].toLowerCase()); - return this.token(); - }, - - peek: function () { - var tt; - if (this.lookahead) { - tt = this.tokens[(this.tokenIndex + this.lookahead) & 3].type; - } else { - tt = this.get(); - this.unget(); - } - return tt; - }, - - peekOnSameLine: function () { - this.scanNewlines = true; - var tt = this.peek(); - this.scanNewlines = false; - return tt; - }, - - get: function () { - var token; - while (this.lookahead) { - --this.lookahead; - this.tokenIndex = (this.tokenIndex + 1) & 3; - token = this.tokens[this.tokenIndex]; - if (token.type != NEWLINE || this.scanNewlines) - return token.type; - } - - for (;;) { - var input = this.input(); - var rx = this.scanNewlines ? /^[ \t]+/ : /^\s+/; - var match = input.match(rx); - if (match) { - var spaces = match[0]; - this.cursor += spaces.length; - var newlines = spaces.match(/\n/g); - if (newlines) - this.lineno += newlines.length; - input = this.input(); - } - - if (!(match = input.match(/^\/(?:\*(?:.|\n)*?\*\/|\/.*)/))) - break; - var comment = match[0]; - this.cursor += comment.length; - newlines = comment.match(/\n/g); - if (newlines) - this.lineno += newlines.length - } - - this.tokenIndex = (this.tokenIndex + 1) & 3; - token = this.tokens[this.tokenIndex]; - if (!token) - this.tokens[this.tokenIndex] = token = {}; - if (!input) - return token.type = END; - if ((match = input.match(fpRegExp))) { - token.type = NUMBER; - token.value = parseFloat(match[0]); - } else if ((match = input.match(/^0[xX][\da-fA-F]+|^0[0-7]*|^\d+/))) { - token.type = NUMBER; - token.value = parseInt(match[0]); - } else if ((match = input.match(/^((\$\w*)|(\w+))/))) { - var id = match[0]; - token.type = keywords[id] || IDENTIFIER; - token.value = id; - } else if ((match = input.match(/^"(?:\\.|[^"])*"|^'(?:[^']|\\.)*'/))) { - token.type = STRING; - token.value = eval(match[0]); - } else if (this.scanOperand && - (match = input.match(/^\/((?:\\.|[^\/])+)\/([gi]*)/))) { - token.type = REGEXP; - token.value = new RegExp(match[1], match[2]); - } else if ((match = input.match(opRegExp))) { - var op = match[0]; - if (assignOps[op] && input[op.length] == '=') { - token.type = ASSIGN; - token.assignOp = GLOBAL[opTypeNames[op]]; - match[0] += '='; - } else { - token.type = GLOBAL[opTypeNames[op]]; - if (this.scanOperand && - (token.type == PLUS || token.type == MINUS)) { - token.type += UNARY_PLUS - PLUS; - } - token.assignOp = null; - } - //debug('token.value => '+op+', token.type => '+token.type); - token.value = op; - } else { - throw this.newSyntaxError("Illegal token"); - } - - token.start = this.cursor; - this.cursor += match[0].length; - token.end = this.cursor; - token.lineno = this.lineno; - return token.type; - }, - - unget: function () { - if (++this.lookahead == 4) throw "PANIC: too much lookahead!"; - this.tokenIndex = (this.tokenIndex - 1) & 3; - }, - - newSyntaxError: function (m) { - var e = new SyntaxError(m, this.filename, this.lineno); - e.source = this.source; - e.cursor = this.cursor; - return e; - } -}; - -function CompilerContext(inFunction) { - this.inFunction = inFunction; - this.stmtStack = []; - this.funDecls = []; - this.varDecls = []; -} - -var CCp = CompilerContext.prototype; -CCp.bracketLevel = CCp.curlyLevel = CCp.parenLevel = CCp.hookLevel = 0; -CCp.ecmaStrictMode = CCp.inForLoopInit = false; - -function Script(t, x) { - var n = Statements(t, x); - n.type = SCRIPT; - n.funDecls = x.funDecls; - n.varDecls = x.varDecls; - return n; -} - -// Node extends Array, which we extend slightly with a top-of-stack method. -Array.prototype.top = function() { - return this.length && this[this.length-1]; -} - -function NarcNode(t, type) { - var token = t.token(); - if (token) { - this.type = type || token.type; - this.value = token.value; - this.lineno = token.lineno; - this.start = token.start; - this.end = token.end; - } else { - this.type = type; - this.lineno = t.lineno; - } - this.tokenizer = t; - for (var i = 2; i < arguments.length; i++) - this.push(arguments[i]); -} - -var Np = NarcNode.prototype = new Array(); -Np.constructor = NarcNode; -Np.$length = 0; -Np.toSource = Object.prototype.toSource; - -// Always use push to add operands to an expression, to update start and end. -Np.push = function (kid) { - if (kid.start < this.start) - this.start = kid.start; - if (this.end < kid.end) - this.end = kid.end; - //debug('length before => '+this.$length); - this[this.$length] = kid; - this.$length++; - //debug('length after => '+this.$length); -} - -NarcNode.indentLevel = 0; - -function tokenstr(tt) { - var t = tokens[tt]; - return /^\W/.test(t) ? opTypeNames[t] : t.toUpperCase(); -} - -Np.toString = function () { - var a = []; - for (var i in this) { - if (this.hasOwnProperty(i) && i != 'type') - a.push({id: i, value: this[i]}); - } - a.sort(function (a,b) { return (a.id < b.id) ? -1 : 1; }); - INDENTATION = " "; - var n = ++NarcNode.indentLevel; - var s = "{\n" + INDENTATION.repeat(n) + "type: " + tokenstr(this.type); - for (i = 0; i < a.length; i++) - s += ",\n" + INDENTATION.repeat(n) + a[i].id + ": " + a[i].value; - n = --NarcNode.indentLevel; - s += "\n" + INDENTATION.repeat(n) + "}"; - return s; -} - -Np.getSource = function () { - return this.tokenizer.source.slice(this.start, this.end); -}; - -Np.filename = function () { return this.tokenizer.filename; }; - -String.prototype.repeat = function (n) { - var s = "", t = this + s; - while (--n >= 0) - s += t; - return s; -} - -// Statement stack and nested statement handler. -function nest(t, x, node, func, end) { - x.stmtStack.push(node); - var n = func(t, x); - x.stmtStack.pop(); - end && t.mustMatch(end); - return n; -} - -function Statements(t, x) { - var n = new NarcNode(t, BLOCK); - x.stmtStack.push(n); - while (!t.done() && t.peek() != RIGHT_CURLY) - n.push(Statement(t, x)); - x.stmtStack.pop(); - return n; -} - -function Block(t, x) { - t.mustMatch(LEFT_CURLY); - var n = Statements(t, x); - t.mustMatch(RIGHT_CURLY); - return n; -} - -DECLARED_FORM = 0; EXPRESSED_FORM = 1; STATEMENT_FORM = 2; - -function Statement(t, x) { - var i, label, n, n2, ss, tt = t.get(); - - // Cases for statements ending in a right curly return early, avoiding the - // common semicolon insertion magic after this switch. - switch (tt) { - case FUNCTION: - return FunctionDefinition(t, x, true, - (x.stmtStack.length > 1) - ? STATEMENT_FORM - : DECLARED_FORM); - - case LEFT_CURLY: - n = Statements(t, x); - t.mustMatch(RIGHT_CURLY); - return n; - - case IF: - n = new NarcNode(t); - n.condition = ParenExpression(t, x); - x.stmtStack.push(n); - n.thenPart = Statement(t, x); - n.elsePart = t.match(ELSE) ? Statement(t, x) : null; - x.stmtStack.pop(); - return n; - - case SWITCH: - n = new NarcNode(t); - t.mustMatch(LEFT_PAREN); - n.discriminant = Expression(t, x); - t.mustMatch(RIGHT_PAREN); - n.cases = []; - n.defaultIndex = -1; - x.stmtStack.push(n); - t.mustMatch(LEFT_CURLY); - while ((tt = t.get()) != RIGHT_CURLY) { - switch (tt) { - case DEFAULT: - if (n.defaultIndex >= 0) - throw t.newSyntaxError("More than one switch default"); - // FALL THROUGH - case CASE: - n2 = new NarcNode(t); - if (tt == DEFAULT) - n.defaultIndex = n.cases.length; - else - n2.caseLabel = Expression(t, x, COLON); - break; - default: - throw t.newSyntaxError("Invalid switch case"); - } - t.mustMatch(COLON); - n2.statements = new NarcNode(t, BLOCK); - while ((tt=t.peek()) != CASE && tt != DEFAULT && tt != RIGHT_CURLY) - n2.statements.push(Statement(t, x)); - n.cases.push(n2); - } - x.stmtStack.pop(); - return n; - - case FOR: - n = new NarcNode(t); - n.isLoop = true; - t.mustMatch(LEFT_PAREN); - if ((tt = t.peek()) != SEMICOLON) { - x.inForLoopInit = true; - if (tt == VAR || tt == CONST) { - t.get(); - n2 = Variables(t, x); - } else { - n2 = Expression(t, x); - } - x.inForLoopInit = false; - } - if (n2 && t.match(IN)) { - n.type = FOR_IN; - if (n2.type == VAR) { - if (n2.$length != 1) { - throw new SyntaxError("Invalid for..in left-hand side", - t.filename, n2.lineno); - } - - // NB: n2[0].type == IDENTIFIER and n2[0].value == n2[0].name. - n.iterator = n2[0]; - n.varDecl = n2; - } else { - n.iterator = n2; - n.varDecl = null; - } - n.object = Expression(t, x); - } else { - n.setup = n2 || null; - t.mustMatch(SEMICOLON); - n.condition = (t.peek() == SEMICOLON) ? null : Expression(t, x); - t.mustMatch(SEMICOLON); - n.update = (t.peek() == RIGHT_PAREN) ? null : Expression(t, x); - } - t.mustMatch(RIGHT_PAREN); - n.body = nest(t, x, n, Statement); - return n; - - case WHILE: - n = new NarcNode(t); - n.isLoop = true; - n.condition = ParenExpression(t, x); - n.body = nest(t, x, n, Statement); - return n; - - case DO: - n = new NarcNode(t); - n.isLoop = true; - n.body = nest(t, x, n, Statement, WHILE); - n.condition = ParenExpression(t, x); - if (!x.ecmaStrictMode) { - // <script language="JavaScript"> (without version hints) may need - // automatic semicolon insertion without a newline after do-while. - // See http://bugzilla.mozilla.org/show_bug.cgi?id=238945. - t.match(SEMICOLON); - return n; - } - break; - - case BREAK: - case CONTINUE: - n = new NarcNode(t); - if (t.peekOnSameLine() == IDENTIFIER) { - t.get(); - n.label = t.token().value; - } - ss = x.stmtStack; - i = ss.length; - label = n.label; - if (label) { - do { - if (--i < 0) - throw t.newSyntaxError("Label not found"); - } while (ss[i].label != label); - } else { - do { - if (--i < 0) { - throw t.newSyntaxError("Invalid " + ((tt == BREAK) - ? "break" - : "continue")); - } - } while (!ss[i].isLoop && (tt != BREAK || ss[i].type != SWITCH)); - } - n.target = ss[i]; - break; - - case TRY: - n = new NarcNode(t); - n.tryBlock = Block(t, x); - n.catchClauses = []; - while (t.match(CATCH)) { - n2 = new NarcNode(t); - t.mustMatch(LEFT_PAREN); - n2.varName = t.mustMatch(IDENTIFIER).value; - if (t.match(IF)) { - if (x.ecmaStrictMode) - throw t.newSyntaxError("Illegal catch guard"); - if (n.catchClauses.length && !n.catchClauses.top().guard) - throw t.newSyntaxError("Guarded catch after unguarded"); - n2.guard = Expression(t, x); - } else { - n2.guard = null; - } - t.mustMatch(RIGHT_PAREN); - n2.block = Block(t, x); - n.catchClauses.push(n2); - } - if (t.match(FINALLY)) - n.finallyBlock = Block(t, x); - if (!n.catchClauses.length && !n.finallyBlock) - throw t.newSyntaxError("Invalid try statement"); - return n; - - case CATCH: - case FINALLY: - throw t.newSyntaxError(tokens[tt] + " without preceding try"); - - case THROW: - n = new NarcNode(t); - n.exception = Expression(t, x); - break; - - case RETURN: - if (!x.inFunction) - throw t.newSyntaxError("Invalid return"); - n = new NarcNode(t); - tt = t.peekOnSameLine(); - if (tt != END && tt != NEWLINE && tt != SEMICOLON && tt != RIGHT_CURLY) - n.value = Expression(t, x); - break; - - case WITH: - n = new NarcNode(t); - n.object = ParenExpression(t, x); - n.body = nest(t, x, n, Statement); - return n; - - case VAR: - case CONST: - n = Variables(t, x); - break; - - case DEBUGGER: - n = new NarcNode(t); - break; - - case REQUIRE: - n = new NarcNode(t); - n.classPath = ParenExpression(t, x); - break; - - case NEWLINE: - case SEMICOLON: - n = new NarcNode(t, SEMICOLON); - n.expression = null; - return n; - - default: - if (tt == IDENTIFIER && t.peek() == COLON) { - label = t.token().value; - ss = x.stmtStack; - for (i = ss.length-1; i >= 0; --i) { - if (ss[i].label == label) - throw t.newSyntaxError("Duplicate label"); - } - t.get(); - n = new NarcNode(t, LABEL); - n.label = label; - n.statement = nest(t, x, n, Statement); - return n; - } - - n = new NarcNode(t, SEMICOLON); - t.unget(); - n.expression = Expression(t, x); - n.end = n.expression.end; - break; - } - - if (t.lineno == t.token().lineno) { - tt = t.peekOnSameLine(); - if (tt != END && tt != NEWLINE && tt != SEMICOLON && tt != RIGHT_CURLY) - throw t.newSyntaxError("Missing ; before statement"); - } - t.match(SEMICOLON); - return n; -} - -function FunctionDefinition(t, x, requireName, functionForm) { - var f = new NarcNode(t); - if (f.type != FUNCTION) - f.type = (f.value == "get") ? GETTER : SETTER; - if (t.match(IDENTIFIER)) { - f.name = t.token().value; - } - else if (requireName) - throw t.newSyntaxError("Missing function identifier"); - - t.mustMatch(LEFT_PAREN); - f.params = []; - var tt; - while ((tt = t.get()) != RIGHT_PAREN) { - if (tt != IDENTIFIER) - throw t.newSyntaxError("Missing formal parameter"); - f.params.push(t.token().value); - if (t.peek() != RIGHT_PAREN) - t.mustMatch(COMMA); - } - - t.mustMatch(LEFT_CURLY); - var x2 = new CompilerContext(true); - f.body = Script(t, x2); - t.mustMatch(RIGHT_CURLY); - f.end = t.token().end; - - f.functionForm = functionForm; - if (functionForm == DECLARED_FORM) { - x.funDecls.push(f); - } - - return f; -} - -function Variables(t, x) { - var n = new NarcNode(t); - do { - t.mustMatch(IDENTIFIER); - var n2 = new NarcNode(t); - n2.name = n2.value; - if (t.match(ASSIGN)) { - if (t.token().assignOp) - throw t.newSyntaxError("Invalid variable initialization"); - n2.initializer = Expression(t, x, COMMA); - } - n2.readOnly = (n.type == CONST); - n.push(n2); - x.varDecls.push(n2); - } while (t.match(COMMA)); - return n; -} - -function ParenExpression(t, x) { - t.mustMatch(LEFT_PAREN); - var n = Expression(t, x); - t.mustMatch(RIGHT_PAREN); - return n; -} - -var opPrecedence = { - SEMICOLON: 0, - COMMA: 1, - ASSIGN: 2, HOOK: 2, COLON: 2, CONDITIONAL: 2, - // The above all have to have the same precedence, see bug 330975. - OR: 4, - AND: 5, - BITWISE_OR: 6, - BITWISE_XOR: 7, - BITWISE_AND: 8, - EQ: 9, NE: 9, STRICT_EQ: 9, STRICT_NE: 9, - LT: 10, LE: 10, GE: 10, GT: 10, IN: 10, INSTANCEOF: 10, - LSH: 11, RSH: 11, URSH: 11, - PLUS: 12, MINUS: 12, - MUL: 13, DIV: 13, MOD: 13, - DELETE: 14, VOID: 14, TYPEOF: 14, // PRE_INCREMENT: 14, PRE_DECREMENT: 14, - NOT: 14, BITWISE_NOT: 14, UNARY_PLUS: 14, UNARY_MINUS: 14, - INCREMENT: 15, DECREMENT: 15, // postfix - NEW: 16, - DOT: 17 -}; - -// Map operator type code to precedence. -for (i in opPrecedence) - opPrecedence[GLOBAL[i]] = opPrecedence[i]; - -var opArity = { - COMMA: -2, - ASSIGN: 2, - CONDITIONAL: 3, - OR: 2, - AND: 2, - BITWISE_OR: 2, - BITWISE_XOR: 2, - BITWISE_AND: 2, - EQ: 2, NE: 2, STRICT_EQ: 2, STRICT_NE: 2, - LT: 2, LE: 2, GE: 2, GT: 2, IN: 2, INSTANCEOF: 2, - LSH: 2, RSH: 2, URSH: 2, - PLUS: 2, MINUS: 2, - MUL: 2, DIV: 2, MOD: 2, - DELETE: 1, VOID: 1, TYPEOF: 1, // PRE_INCREMENT: 1, PRE_DECREMENT: 1, - NOT: 1, BITWISE_NOT: 1, UNARY_PLUS: 1, UNARY_MINUS: 1, - INCREMENT: 1, DECREMENT: 1, // postfix - NEW: 1, NEW_WITH_ARGS: 2, DOT: 2, INDEX: 2, CALL: 2, - ARRAY_INIT: 1, OBJECT_INIT: 1, GROUP: 1 -}; - -// Map operator type code to arity. -for (i in opArity) - opArity[GLOBAL[i]] = opArity[i]; - -function Expression(t, x, stop) { - var n, id, tt, operators = [], operands = []; - var bl = x.bracketLevel, cl = x.curlyLevel, pl = x.parenLevel, - hl = x.hookLevel; - - function reduce() { - //debug('OPERATORS => '+operators); - var n = operators.pop(); - var op = n.type; - var arity = opArity[op]; - if (arity == -2) { - // Flatten left-associative trees. - var left = operands.length >= 2 && operands[operands.length-2]; - if (left.type == op) { - var right = operands.pop(); - left.push(right); - return left; - } - arity = 2; - } - - // Always use push to add operands to n, to update start and end. - var a = operands.splice(operands.length - arity, operands.length); - for (var i = 0; i < arity; i++) { - n.push(a[i]); - } - - // Include closing bracket or postfix operator in [start,end). - if (n.end < t.token().end) - n.end = t.token().end; - - operands.push(n); - return n; - } - -loop: - while ((tt = t.get()) != END) { - //debug('TT => '+tokens[tt]); - if (tt == stop && - x.bracketLevel == bl && x.curlyLevel == cl && x.parenLevel == pl && - x.hookLevel == hl) { - // Stop only if tt matches the optional stop parameter, and that - // token is not quoted by some kind of bracket. - break; - } - switch (tt) { - case SEMICOLON: - // NB: cannot be empty, Statement handled that. - break loop; - - case ASSIGN: - case HOOK: - case COLON: - if (t.scanOperand) - break loop; - // Use >, not >=, for right-associative ASSIGN and HOOK/COLON. - while (operators.length && opPrecedence[operators.top().type] > opPrecedence[tt] || - (tt == COLON && operators.top().type == ASSIGN)) { - reduce(); - } - if (tt == COLON) { - n = operators.top(); - if (n.type != HOOK) - throw t.newSyntaxError("Invalid label"); - n.type = CONDITIONAL; - --x.hookLevel; - } else { - operators.push(new NarcNode(t)); - if (tt == ASSIGN) - operands.top().assignOp = t.token().assignOp; - else - ++x.hookLevel; // tt == HOOK - } - t.scanOperand = true; - break; - - case IN: - // An in operator should not be parsed if we're parsing the head of - // a for (...) loop, unless it is in the then part of a conditional - // expression, or parenthesized somehow. - if (x.inForLoopInit && !x.hookLevel && - !x.bracketLevel && !x.curlyLevel && !x.parenLevel) { - break loop; - } - // FALL THROUGH - case COMMA: - // Treat comma as left-associative so reduce can fold left-heavy - // COMMA trees into a single array. - // FALL THROUGH - case OR: - case AND: - case BITWISE_OR: - case BITWISE_XOR: - case BITWISE_AND: - case EQ: case NE: case STRICT_EQ: case STRICT_NE: - case LT: case LE: case GE: case GT: - case INSTANCEOF: - case LSH: case RSH: case URSH: - case PLUS: case MINUS: - case MUL: case DIV: case MOD: - case DOT: - if (t.scanOperand) - break loop; - while (operators.length && opPrecedence[operators.top().type] >= opPrecedence[tt]) - reduce(); - if (tt == DOT) { - t.mustMatch(IDENTIFIER); - operands.push(new NarcNode(t, DOT, operands.pop(), new NarcNode(t))); - } else { - operators.push(new NarcNode(t)); - t.scanOperand = true; - } - break; - - case DELETE: case VOID: case TYPEOF: - case NOT: case BITWISE_NOT: case UNARY_PLUS: case UNARY_MINUS: - case NEW: - if (!t.scanOperand) - break loop; - operators.push(new NarcNode(t)); - break; - - case INCREMENT: case DECREMENT: - if (t.scanOperand) { - operators.push(new NarcNode(t)); // prefix increment or decrement - } else { - // Use >, not >=, so postfix has higher precedence than prefix. - while (operators.length && opPrecedence[operators.top().type] > opPrecedence[tt]) - reduce(); - n = new NarcNode(t, tt, operands.pop()); - n.postfix = true; - operands.push(n); - } - break; - - case FUNCTION: - if (!t.scanOperand) - break loop; - operands.push(FunctionDefinition(t, x, false, EXPRESSED_FORM)); - t.scanOperand = false; - break; - - case NULL: case THIS: case TRUE: case FALSE: - case IDENTIFIER: case NUMBER: case STRING: case REGEXP: - if (!t.scanOperand) - break loop; - operands.push(new NarcNode(t)); - t.scanOperand = false; - break; - - case LEFT_BRACKET: - if (t.scanOperand) { - // Array initialiser. Parse using recursive descent, as the - // sub-grammar here is not an operator grammar. - n = new NarcNode(t, ARRAY_INIT); - while ((tt = t.peek()) != RIGHT_BRACKET) { - if (tt == COMMA) { - t.get(); - n.push(null); - continue; - } - n.push(Expression(t, x, COMMA)); - if (!t.match(COMMA)) - break; - } - t.mustMatch(RIGHT_BRACKET); - operands.push(n); - t.scanOperand = false; - } else { - // Property indexing operator. - operators.push(new NarcNode(t, INDEX)); - t.scanOperand = true; - ++x.bracketLevel; - } - break; - - case RIGHT_BRACKET: - if (t.scanOperand || x.bracketLevel == bl) - break loop; - while (reduce().type != INDEX) - continue; - --x.bracketLevel; - break; - - case LEFT_CURLY: - if (!t.scanOperand) - break loop; - // Object initialiser. As for array initialisers (see above), - // parse using recursive descent. - ++x.curlyLevel; - n = new NarcNode(t, OBJECT_INIT); - object_init: - if (!t.match(RIGHT_CURLY)) { - do { - tt = t.get(); - if ((t.token().value == "get" || t.token().value == "set") && - t.peek() == IDENTIFIER) { - if (x.ecmaStrictMode) - throw t.newSyntaxError("Illegal property accessor"); - n.push(FunctionDefinition(t, x, true, EXPRESSED_FORM)); - } else { - switch (tt) { - case IDENTIFIER: - case NUMBER: - case STRING: - id = new NarcNode(t); - break; - case RIGHT_CURLY: - if (x.ecmaStrictMode) - throw t.newSyntaxError("Illegal trailing ,"); - break object_init; - default: - throw t.newSyntaxError("Invalid property name"); - } - t.mustMatch(COLON); - n.push(new NarcNode(t, PROPERTY_INIT, id, - Expression(t, x, COMMA))); - } - } while (t.match(COMMA)); - t.mustMatch(RIGHT_CURLY); - } - operands.push(n); - t.scanOperand = false; - --x.curlyLevel; - break; - - case RIGHT_CURLY: - if (!t.scanOperand && x.curlyLevel != cl) - throw "PANIC: right curly botch"; - break loop; - - case LEFT_PAREN: - if (t.scanOperand) { - operators.push(new NarcNode(t, GROUP)); - } else { - while (operators.length && opPrecedence[operators.top().type] > opPrecedence[NEW]) - reduce(); - - // Handle () now, to regularize the n-ary case for n > 0. - // We must set scanOperand in case there are arguments and - // the first one is a regexp or unary+/-. - n = operators.top(); - t.scanOperand = true; - if (t.match(RIGHT_PAREN)) { - if (n.type == NEW) { - --operators.length; - n.push(operands.pop()); - } else { - n = new NarcNode(t, CALL, operands.pop(), - new NarcNode(t, LIST)); - } - operands.push(n); - t.scanOperand = false; - break; - } - if (n.type == NEW) - n.type = NEW_WITH_ARGS; - else - operators.push(new NarcNode(t, CALL)); - } - ++x.parenLevel; - break; - - case RIGHT_PAREN: - if (t.scanOperand || x.parenLevel == pl) - break loop; - while ((tt = reduce().type) != GROUP && tt != CALL && - tt != NEW_WITH_ARGS) { - continue; - } - if (tt != GROUP) { - n = operands.top(); - if (n[1].type != COMMA) - n[1] = new NarcNode(t, LIST, n[1]); - else - n[1].type = LIST; - } - --x.parenLevel; - break; - - // Automatic semicolon insertion means we may scan across a newline - // and into the beginning of another statement. If so, break out of - // the while loop and let the t.scanOperand logic handle errors. - default: - break loop; - } - } - if (x.hookLevel != hl) - throw t.newSyntaxError("Missing : after ?"); - if (x.parenLevel != pl) - throw t.newSyntaxError("Missing ) in parenthetical"); - if (x.bracketLevel != bl) - throw t.newSyntaxError("Missing ] in index expression"); - if (t.scanOperand) - throw t.newSyntaxError("Missing operand"); - - // Resume default mode, scanning for operands, not operators. - t.scanOperand = true; - t.unget(); - - while (operators.length) - reduce(); - return operands.pop(); -} - -function parse(s, f, l) { - var t = new Tokenizer(s, f, l); - var x = new CompilerContext(false); - var n = Script(t, x); - if (!t.done()) - throw t.newSyntaxError("Syntax error"); - return n; -} - -debug = function(msg) { - document.body.appendChild(document.createTextNode(msg)); - document.body.appendChild(document.createElement('br')); -} - diff --git a/tests/test_tools/selenium/core/scripts/prototype-1.4.0.js b/tests/test_tools/selenium/core/scripts/prototype-1.4.0.js deleted file mode 100644 index 0e85338b..00000000 --- a/tests/test_tools/selenium/core/scripts/prototype-1.4.0.js +++ /dev/null @@ -1,1781 +0,0 @@ -/* Prototype JavaScript framework, version 1.4.0 - * (c) 2005 Sam Stephenson <sam@conio.net> - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://prototype.conio.net/ - * -/*--------------------------------------------------------------------------*/ - -var Prototype = { - Version: '1.4.0', - ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', - - emptyFunction: function() {}, - K: function(x) {return x} -} - -var Class = { - create: function() { - return function() { - this.initialize.apply(this, arguments); - } - } -} - -var Abstract = new Object(); - -Object.extend = function(destination, source) { - for (property in source) { - destination[property] = source[property]; - } - return destination; -} - -Object.inspect = function(object) { - try { - if (object == undefined) return 'undefined'; - if (object == null) return 'null'; - return object.inspect ? object.inspect() : object.toString(); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } -} - -Function.prototype.bind = function() { - var __method = this, args = $A(arguments), object = args.shift(); - return function() { - return __method.apply(object, args.concat($A(arguments))); - } -} - -Function.prototype.bindAsEventListener = function(object) { - var __method = this; - return function(event) { - return __method.call(object, event || window.event); - } -} - -Object.extend(Number.prototype, { - toColorPart: function() { - var digits = this.toString(16); - if (this < 16) return '0' + digits; - return digits; - }, - - succ: function() { - return this + 1; - }, - - times: function(iterator) { - $R(0, this, true).each(iterator); - return this; - } -}); - -var Try = { - these: function() { - var returnValue; - - for (var i = 0; i < arguments.length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) {} - } - - return returnValue; - } -} - -/*--------------------------------------------------------------------------*/ - -var PeriodicalExecuter = Class.create(); -PeriodicalExecuter.prototype = { - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.callback(); - } finally { - this.currentlyExecuting = false; - } - } - } -} - -/*--------------------------------------------------------------------------*/ - -function $() { - var elements = new Array(); - - for (var i = 0; i < arguments.length; i++) { - var element = arguments[i]; - if (typeof element == 'string') - element = document.getElementById(element); - - if (arguments.length == 1) - return element; - - elements.push(element); - } - - return elements; -} -Object.extend(String.prototype, { - stripTags: function() { - return this.replace(/<\/?[^>]+>/gi, ''); - }, - - stripScripts: function() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - }, - - extractScripts: function() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); - var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - return (this.match(matchAll) || []).map(function(scriptTag) { - return (scriptTag.match(matchOne) || ['', ''])[1]; - }); - }, - - evalScripts: function() { - return this.extractScripts().map(eval); - }, - - escapeHTML: function() { - var div = document.createElement('div'); - var text = document.createTextNode(this); - div.appendChild(text); - return div.innerHTML; - }, - - unescapeHTML: function() { - var div = document.createElement('div'); - div.innerHTML = this.stripTags(); - return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; - }, - - toQueryParams: function() { - var pairs = this.match(/^\??(.*)$/)[1].split('&'); - return pairs.inject({}, function(params, pairString) { - var pair = pairString.split('='); - params[pair[0]] = pair[1]; - return params; - }); - }, - - toArray: function() { - return this.split(''); - }, - - camelize: function() { - var oStringList = this.split('-'); - if (oStringList.length == 1) return oStringList[0]; - - var camelizedString = this.indexOf('-') == 0 - ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) - : oStringList[0]; - - for (var i = 1, len = oStringList.length; i < len; i++) { - var s = oStringList[i]; - camelizedString += s.charAt(0).toUpperCase() + s.substring(1); - } - - return camelizedString; - }, - - inspect: function() { - return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; - } -}); - -String.prototype.parseQuery = String.prototype.toQueryParams; - -var $break = new Object(); -var $continue = new Object(); - -var Enumerable = { - each: function(iterator) { - var index = 0; - try { - this._each(function(value) { - try { - iterator(value, index++); - } catch (e) { - if (e != $continue) throw e; - } - }); - } catch (e) { - if (e != $break) throw e; - } - }, - - all: function(iterator) { - var result = true; - this.each(function(value, index) { - result = result && !!(iterator || Prototype.K)(value, index); - if (!result) throw $break; - }); - return result; - }, - - any: function(iterator) { - var result = true; - this.each(function(value, index) { - if (result = !!(iterator || Prototype.K)(value, index)) - throw $break; - }); - return result; - }, - - collect: function(iterator) { - var results = []; - this.each(function(value, index) { - results.push(iterator(value, index)); - }); - return results; - }, - - detect: function (iterator) { - var result; - this.each(function(value, index) { - if (iterator(value, index)) { - result = value; - throw $break; - } - }); - return result; - }, - - findAll: function(iterator) { - var results = []; - this.each(function(value, index) { - if (iterator(value, index)) - results.push(value); - }); - return results; - }, - - grep: function(pattern, iterator) { - var results = []; - this.each(function(value, index) { - var stringValue = value.toString(); - if (stringValue.match(pattern)) - results.push((iterator || Prototype.K)(value, index)); - }) - return results; - }, - - include: function(object) { - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - }, - - inject: function(memo, iterator) { - this.each(function(value, index) { - memo = iterator(memo, value, index); - }); - return memo; - }, - - invoke: function(method) { - var args = $A(arguments).slice(1); - return this.collect(function(value) { - return value[method].apply(value, args); - }); - }, - - max: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value >= (result || value)) - result = value; - }); - return result; - }, - - min: function(iterator) { - var result; - this.each(function(value, index) { - value = (iterator || Prototype.K)(value, index); - if (value <= (result || value)) - result = value; - }); - return result; - }, - - partition: function(iterator) { - var trues = [], falses = []; - this.each(function(value, index) { - ((iterator || Prototype.K)(value, index) ? - trues : falses).push(value); - }); - return [trues, falses]; - }, - - pluck: function(property) { - var results = []; - this.each(function(value, index) { - results.push(value[property]); - }); - return results; - }, - - reject: function(iterator) { - var results = []; - this.each(function(value, index) { - if (!iterator(value, index)) - results.push(value); - }); - return results; - }, - - sortBy: function(iterator) { - return this.collect(function(value, index) { - return {value: value, criteria: iterator(value, index)}; - }).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - }, - - toArray: function() { - return this.collect(Prototype.K); - }, - - zip: function() { - var iterator = Prototype.K, args = $A(arguments); - if (typeof args.last() == 'function') - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - iterator(value = collections.pluck(index)); - return value; - }); - }, - - inspect: function() { - return '#<Enumerable:' + this.toArray().inspect() + '>'; - } -} - -Object.extend(Enumerable, { - map: Enumerable.collect, - find: Enumerable.detect, - select: Enumerable.findAll, - member: Enumerable.include, - entries: Enumerable.toArray -}); -var $A = Array.from = function(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; - } -} - -Object.extend(Array.prototype, Enumerable); - -Array.prototype._reverse = Array.prototype.reverse; - -Object.extend(Array.prototype, { - _each: function(iterator) { - for (var i = 0; i < this.length; i++) - iterator(this[i]); - }, - - clear: function() { - this.length = 0; - return this; - }, - - first: function() { - return this[0]; - }, - - last: function() { - return this[this.length - 1]; - }, - - compact: function() { - return this.select(function(value) { - return value != undefined || value != null; - }); - }, - - flatten: function() { - return this.inject([], function(array, value) { - return array.concat(value.constructor == Array ? - value.flatten() : [value]); - }); - }, - - without: function() { - var values = $A(arguments); - return this.select(function(value) { - return !values.include(value); - }); - }, - - indexOf: function(object) { - for (var i = 0; i < this.length; i++) - if (this[i] == object) return i; - return -1; - }, - - reverse: function(inline) { - return (inline !== false ? this : this.toArray())._reverse(); - }, - - shift: function() { - var result = this[0]; - for (var i = 0; i < this.length - 1; i++) - this[i] = this[i + 1]; - this.length--; - return result; - }, - - inspect: function() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } -}); -var Hash = { - _each: function(iterator) { - for (key in this) { - var value = this[key]; - if (typeof value == 'function') continue; - - var pair = [key, value]; - pair.key = key; - pair.value = value; - iterator(pair); - } - }, - - keys: function() { - return this.pluck('key'); - }, - - values: function() { - return this.pluck('value'); - }, - - merge: function(hash) { - return $H(hash).inject($H(this), function(mergedHash, pair) { - mergedHash[pair.key] = pair.value; - return mergedHash; - }); - }, - - toQueryString: function() { - return this.map(function(pair) { - return pair.map(encodeURIComponent).join('='); - }).join('&'); - }, - - inspect: function() { - return '#<Hash:{' + this.map(function(pair) { - return pair.map(Object.inspect).join(': '); - }).join(', ') + '}>'; - } -} - -function $H(object) { - var hash = Object.extend({}, object || {}); - Object.extend(hash, Enumerable); - Object.extend(hash, Hash); - return hash; -} -ObjectRange = Class.create(); -Object.extend(ObjectRange.prototype, Enumerable); -Object.extend(ObjectRange.prototype, { - initialize: function(start, end, exclusive) { - this.start = start; - this.end = end; - this.exclusive = exclusive; - }, - - _each: function(iterator) { - var value = this.start; - do { - iterator(value); - value = value.succ(); - } while (this.include(value)); - }, - - include: function(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } -}); - -var $R = function(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var Ajax = { - getTransport: function() { - return Try.these( - function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')}, - function() {return new XMLHttpRequest()} - ) || false; - }, - - activeRequestCount: 0 -} - -Ajax.Responders = { - responders: [], - - _each: function(iterator) { - this.responders._each(iterator); - }, - - register: function(responderToAdd) { - if (!this.include(responderToAdd)) - this.responders.push(responderToAdd); - }, - - unregister: function(responderToRemove) { - this.responders = this.responders.without(responderToRemove); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (responder[callback] && typeof responder[callback] == 'function') { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) {} - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { - Ajax.activeRequestCount++; - }, - - onComplete: function() { - Ajax.activeRequestCount--; - } -}); - -Ajax.Base = function() {}; -Ajax.Base.prototype = { - setOptions: function(options) { - this.options = { - method: 'post', - asynchronous: true, - parameters: '' - } - Object.extend(this.options, options || {}); - }, - - responseIsSuccess: function() { - return this.transport.status == undefined - || this.transport.status == 0 - || (this.transport.status >= 200 && this.transport.status < 300); - }, - - responseIsFailure: function() { - return !this.responseIsSuccess(); - } -} - -Ajax.Request = Class.create(); -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; - -Ajax.Request.prototype = Object.extend(new Ajax.Base(), { - initialize: function(url, options) { - this.transport = Ajax.getTransport(); - this.setOptions(options); - this.request(url); - }, - - request: function(url) { - var parameters = this.options.parameters || ''; - if (parameters.length > 0) parameters += '&_='; - - try { - this.url = url; - if (this.options.method == 'get' && parameters.length > 0) - this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; - - Ajax.Responders.dispatch('onCreate', this, this.transport); - - this.transport.open(this.options.method, this.url, - this.options.asynchronous); - - if (this.options.asynchronous) { - this.transport.onreadystatechange = this.onStateChange.bind(this); - setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); - } - - this.setRequestHeaders(); - - var body = this.options.postBody ? this.options.postBody : parameters; - this.transport.send(this.options.method == 'post' ? body : null); - - } catch (e) { - this.dispatchException(e); - } - }, - - setRequestHeaders: function() { - var requestHeaders = - ['X-Requested-With', 'XMLHttpRequest', - 'X-Prototype-Version', Prototype.Version]; - - if (this.options.method == 'post') { - requestHeaders.push('Content-type', - 'application/x-www-form-urlencoded'); - - /* Force "Connection: close" for Mozilla browsers to work around - * a bug where XMLHttpReqeuest sends an incorrect Content-length - * header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType) - requestHeaders.push('Connection', 'close'); - } - - if (this.options.requestHeaders) - requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); - - for (var i = 0; i < requestHeaders.length; i += 2) - this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState != 1) - this.respondToReadyState(this.transport.readyState); - }, - - header: function(name) { - try { - return this.transport.getResponseHeader(name); - } catch (e) {} - }, - - evalJSON: function() { - try { - return eval(this.header('X-JSON')); - } catch (e) {} - }, - - evalResponse: function() { - try { - return eval(this.transport.responseText); - } catch (e) { - this.dispatchException(e); - } - }, - - respondToReadyState: function(readyState) { - var event = Ajax.Request.Events[readyState]; - var transport = this.transport, json = this.evalJSON(); - - if (event == 'Complete') { - try { - (this.options['on' + this.transport.status] - || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(transport, json); - } catch (e) { - this.dispatchException(e); - } - - if ((this.header('Content-type') || '').match(/^text\/javascript/i)) - this.evalResponse(); - } - - try { - (this.options['on' + event] || Prototype.emptyFunction)(transport, json); - Ajax.Responders.dispatch('on' + event, this, transport, json); - } catch (e) { - this.dispatchException(e); - } - - /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ - if (event == 'Complete') - this.transport.onreadystatechange = Prototype.emptyFunction; - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Updater = Class.create(); - -Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { - initialize: function(container, url, options) { - this.containers = { - success: container.success ? $(container.success) : $(container), - failure: container.failure ? $(container.failure) : - (container.success ? null : $(container)) - } - - this.transport = Ajax.getTransport(); - this.setOptions(options); - - var onComplete = this.options.onComplete || Prototype.emptyFunction; - this.options.onComplete = (function(transport, object) { - this.updateContent(); - onComplete(transport, object); - }).bind(this); - - this.request(url); - }, - - updateContent: function() { - var receiver = this.responseIsSuccess() ? - this.containers.success : this.containers.failure; - var response = this.transport.responseText; - - if (!this.options.evalScripts) - response = response.stripScripts(); - - if (receiver) { - if (this.options.insertion) { - new this.options.insertion(receiver, response); - } else { - Element.update(receiver, response); - } - } - - if (this.responseIsSuccess()) { - if (this.onComplete) - setTimeout(this.onComplete.bind(this), 10); - } - } -}); - -Ajax.PeriodicalUpdater = Class.create(); -Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { - initialize: function(container, url, options) { - this.setOptions(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = {}; - this.container = container; - this.url = url; - - this.start(); - }, - - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - stop: function() { - this.updater.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(request) { - if (this.options.decay) { - this.decay = (request.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = request.responseText; - } - this.timer = setTimeout(this.onTimerEvent.bind(this), - this.decay * this.frequency * 1000); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); -document.getElementsByClassName = function(className, parentElement) { - var children = ($(parentElement) || document.body).getElementsByTagName('*'); - return $A(children).inject([], function(elements, child) { - if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) - elements.push(child); - return elements; - }); -} - -/*--------------------------------------------------------------------------*/ - -if (!window.Element) { - var Element = new Object(); -} - -Object.extend(Element, { - visible: function(element) { - return $(element).style.display != 'none'; - }, - - toggle: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - Element[Element.visible(element) ? 'hide' : 'show'](element); - } - }, - - hide: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = 'none'; - } - }, - - show: function() { - for (var i = 0; i < arguments.length; i++) { - var element = $(arguments[i]); - element.style.display = ''; - } - }, - - remove: function(element) { - element = $(element); - element.parentNode.removeChild(element); - }, - - update: function(element, html) { - $(element).innerHTML = html.stripScripts(); - setTimeout(function() {html.evalScripts()}, 10); - }, - - getHeight: function(element) { - element = $(element); - return element.offsetHeight; - }, - - classNames: function(element) { - return new Element.ClassNames(element); - }, - - hasClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).include(className); - }, - - addClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).add(className); - }, - - removeClassName: function(element, className) { - if (!(element = $(element))) return; - return Element.classNames(element).remove(className); - }, - - // removes whitespace-only text node children - cleanWhitespace: function(element) { - element = $(element); - for (var i = 0; i < element.childNodes.length; i++) { - var node = element.childNodes[i]; - if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) - Element.remove(node); - } - }, - - empty: function(element) { - return $(element).innerHTML.match(/^\s*$/); - }, - - scrollTo: function(element) { - element = $(element); - var x = element.x ? element.x : element.offsetLeft, - y = element.y ? element.y : element.offsetTop; - window.scrollTo(x, y); - }, - - getStyle: function(element, style) { - element = $(element); - var value = element.style[style.camelize()]; - 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.camelize()]; - } - } - - if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) - if (Element.getStyle(element, 'position') == 'static') value = 'auto'; - - return value == 'auto' ? null : value; - }, - - setStyle: function(element, style) { - element = $(element); - for (name in style) - element.style[name.camelize()] = style[name]; - }, - - getDimensions: function(element) { - element = $(element); - if (Element.getStyle(element, 'display') != 'none') - return {width: element.offsetWidth, height: element.offsetHeight}; - - // All *Width and *Height properties give 0 on elements with display none, - // so enable the element temporarily - var els = element.style; - var originalVisibility = els.visibility; - var originalPosition = els.position; - els.visibility = 'hidden'; - els.position = 'absolute'; - els.display = ''; - var originalWidth = element.clientWidth; - var originalHeight = element.clientHeight; - els.display = 'none'; - els.position = originalPosition; - els.visibility = originalVisibility; - return {width: originalWidth, height: originalHeight}; - }, - - makePositioned: function(element) { - element = $(element); - var pos = Element.getStyle(element, 'position'); - if (pos == 'static' || !pos) { - element._madePositioned = true; - element.style.position = 'relative'; - // Opera returns the offset relative to the positioning context, when an - // element is position relative but top and left have not been defined - if (window.opera) { - element.style.top = 0; - element.style.left = 0; - } - } - }, - - undoPositioned: function(element) { - element = $(element); - if (element._madePositioned) { - element._madePositioned = undefined; - element.style.position = - element.style.top = - element.style.left = - element.style.bottom = - element.style.right = ''; - } - }, - - makeClipping: function(element) { - element = $(element); - if (element._overflow) return; - element._overflow = element.style.overflow; - if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') - element.style.overflow = 'hidden'; - }, - - undoClipping: function(element) { - element = $(element); - if (element._overflow) return; - element.style.overflow = element._overflow; - element._overflow = undefined; - } -}); - -var Toggle = new Object(); -Toggle.display = Element.toggle; - -/*--------------------------------------------------------------------------*/ - -Abstract.Insertion = function(adjacency) { - this.adjacency = adjacency; -} - -Abstract.Insertion.prototype = { - initialize: function(element, content) { - this.element = $(element); - this.content = content.stripScripts(); - - if (this.adjacency && this.element.insertAdjacentHTML) { - try { - this.element.insertAdjacentHTML(this.adjacency, this.content); - } catch (e) { - if (this.element.tagName.toLowerCase() == 'tbody') { - this.insertContent(this.contentFromAnonymousTable()); - } else { - throw e; - } - } - } else { - this.range = this.element.ownerDocument.createRange(); - if (this.initializeRange) this.initializeRange(); - this.insertContent([this.range.createContextualFragment(this.content)]); - } - - setTimeout(function() {content.evalScripts()}, 10); - }, - - contentFromAnonymousTable: function() { - var div = document.createElement('div'); - div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>'; - return $A(div.childNodes[0].childNodes[0].childNodes); - } -} - -var Insertion = new Object(); - -Insertion.Before = Class.create(); -Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { - initializeRange: function() { - this.range.setStartBefore(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, this.element); - }).bind(this)); - } -}); - -Insertion.Top = Class.create(); -Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(true); - }, - - insertContent: function(fragments) { - fragments.reverse(false).each((function(fragment) { - this.element.insertBefore(fragment, this.element.firstChild); - }).bind(this)); - } -}); - -Insertion.Bottom = Class.create(); -Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { - initializeRange: function() { - this.range.selectNodeContents(this.element); - this.range.collapse(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.appendChild(fragment); - }).bind(this)); - } -}); - -Insertion.After = Class.create(); -Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { - initializeRange: function() { - this.range.setStartAfter(this.element); - }, - - insertContent: function(fragments) { - fragments.each((function(fragment) { - this.element.parentNode.insertBefore(fragment, - this.element.nextSibling); - }).bind(this)); - } -}); - -/*--------------------------------------------------------------------------*/ - -Element.ClassNames = Class.create(); -Element.ClassNames.prototype = { - initialize: function(element) { - this.element = $(element); - }, - - _each: function(iterator) { - this.element.className.split(/\s+/).select(function(name) { - return name.length > 0; - })._each(iterator); - }, - - set: function(className) { - this.element.className = className; - }, - - add: function(classNameToAdd) { - if (this.include(classNameToAdd)) return; - this.set(this.toArray().concat(classNameToAdd).join(' ')); - }, - - remove: function(classNameToRemove) { - if (!this.include(classNameToRemove)) return; - this.set(this.select(function(className) { - return className != classNameToRemove; - }).join(' ')); - }, - - toString: function() { - return this.toArray().join(' '); - } -} - -Object.extend(Element.ClassNames.prototype, Enumerable); -var Field = { - clear: function() { - for (var i = 0; i < arguments.length; i++) - $(arguments[i]).value = ''; - }, - - focus: function(element) { - $(element).focus(); - }, - - present: function() { - for (var i = 0; i < arguments.length; i++) - if ($(arguments[i]).value == '') return false; - return true; - }, - - select: function(element) { - $(element).select(); - }, - - activate: function(element) { - element = $(element); - element.focus(); - if (element.select) - element.select(); - } -} - -/*--------------------------------------------------------------------------*/ - -var Form = { - serialize: function(form) { - var elements = Form.getElements($(form)); - var queryComponents = new Array(); - - for (var i = 0; i < elements.length; i++) { - var queryComponent = Form.Element.serialize(elements[i]); - if (queryComponent) - queryComponents.push(queryComponent); - } - - return queryComponents.join('&'); - }, - - getElements: function(form) { - form = $(form); - var elements = new Array(); - - for (tagName in Form.Element.Serializers) { - var tagElements = form.getElementsByTagName(tagName); - for (var j = 0; j < tagElements.length; j++) - elements.push(tagElements[j]); - } - return elements; - }, - - getInputs: function(form, typeName, name) { - form = $(form); - var inputs = form.getElementsByTagName('input'); - - if (!typeName && !name) - return inputs; - - var matchingInputs = new Array(); - for (var i = 0; i < inputs.length; i++) { - var input = inputs[i]; - if ((typeName && input.type != typeName) || - (name && input.name != name)) - continue; - matchingInputs.push(input); - } - - return matchingInputs; - }, - - disable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.blur(); - element.disabled = 'true'; - } - }, - - enable: function(form) { - var elements = Form.getElements(form); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - element.disabled = ''; - } - }, - - findFirstElement: function(form) { - return Form.getElements(form).find(function(element) { - return element.type != 'hidden' && !element.disabled && - ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); - }); - }, - - focusFirstElement: function(form) { - Field.activate(Form.findFirstElement(form)); - }, - - reset: function(form) { - $(form).reset(); - } -} - -Form.Element = { - serialize: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) { - var key = encodeURIComponent(parameter[0]); - if (key.length == 0) return; - - if (parameter[1].constructor != Array) - parameter[1] = [parameter[1]]; - - return parameter[1].map(function(value) { - return key + '=' + encodeURIComponent(value); - }).join('&'); - } - }, - - getValue: function(element) { - element = $(element); - var method = element.tagName.toLowerCase(); - var parameter = Form.Element.Serializers[method](element); - - if (parameter) - return parameter[1]; - } -} - -Form.Element.Serializers = { - input: function(element) { - switch (element.type.toLowerCase()) { - case 'submit': - case 'hidden': - case 'password': - case 'text': - return Form.Element.Serializers.textarea(element); - case 'checkbox': - case 'radio': - return Form.Element.Serializers.inputSelector(element); - } - return false; - }, - - inputSelector: function(element) { - if (element.checked) - return [element.name, element.value]; - }, - - textarea: function(element) { - return [element.name, element.value]; - }, - - select: function(element) { - return Form.Element.Serializers[element.type == 'select-one' ? - 'selectOne' : 'selectMany'](element); - }, - - selectOne: function(element) { - var value = '', opt, index = element.selectedIndex; - if (index >= 0) { - opt = element.options[index]; - value = opt.value; - if (!value && !('value' in opt)) - value = opt.text; - } - return [element.name, value]; - }, - - selectMany: function(element) { - var value = new Array(); - for (var i = 0; i < element.length; i++) { - var opt = element.options[i]; - if (opt.selected) { - var optValue = opt.value; - if (!optValue && !('value' in opt)) - optValue = opt.text; - value.push(optValue); - } - } - return [element.name, value]; - } -} - -/*--------------------------------------------------------------------------*/ - -var $F = Form.Element.getValue; - -/*--------------------------------------------------------------------------*/ - -Abstract.TimedObserver = function() {} -Abstract.TimedObserver.prototype = { - initialize: function(element, frequency, callback) { - this.frequency = frequency; - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - this.registerCallback(); - }, - - registerCallback: function() { - setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - onTimerEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - } -} - -Form.Element.Observer = Class.create(); -Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.Observer = Class.create(); -Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -Abstract.EventObserver = function() {} -Abstract.EventObserver.prototype = { - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - var elements = Form.getElements(this.element); - for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - case 'password': - case 'text': - case 'textarea': - case 'select-one': - case 'select-multiple': - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -} - -Form.Element.EventObserver = Class.create(); -Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -Form.EventObserver = Class.create(); -Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { - getValue: function() { - return Form.serialize(this.element); - } -}); -if (!window.Event) { - var Event = new Object(); -} - -Object.extend(Event, { - KEY_BACKSPACE: 8, - KEY_TAB: 9, - KEY_RETURN: 13, - KEY_ESC: 27, - KEY_LEFT: 37, - KEY_UP: 38, - KEY_RIGHT: 39, - KEY_DOWN: 40, - KEY_DELETE: 46, - - element: function(event) { - return event.target || event.srcElement; - }, - - isLeftClick: function(event) { - return (((event.which) && (event.which == 1)) || - ((event.button) && (event.button == 1))); - }, - - pointerX: function(event) { - return event.pageX || (event.clientX + - (document.documentElement.scrollLeft || document.body.scrollLeft)); - }, - - pointerY: function(event) { - return event.pageY || (event.clientY + - (document.documentElement.scrollTop || document.body.scrollTop)); - }, - - stop: function(event) { - if (event.preventDefault) { - event.preventDefault(); - event.stopPropagation(); - } else { - event.returnValue = false; - event.cancelBubble = true; - } - }, - - // find the first node with the given tagName, starting from the - // node the event was triggered on; traverses the DOM upwards - findElement: function(event, tagName) { - var element = Event.element(event); - while (element.parentNode && (!element.tagName || - (element.tagName.toUpperCase() != tagName.toUpperCase()))) - element = element.parentNode; - return element; - }, - - observers: false, - - _observeAndCache: function(element, name, observer, useCapture) { - if (!this.observers) this.observers = []; - if (element.addEventListener) { - this.observers.push([element, name, observer, useCapture]); - element.addEventListener(name, observer, useCapture); - } else if (element.attachEvent) { - this.observers.push([element, name, observer, useCapture]); - element.attachEvent('on' + name, observer); - } - }, - - unloadCache: function() { - if (!Event.observers) return; - for (var i = 0; i < Event.observers.length; i++) { - Event.stopObserving.apply(this, Event.observers[i]); - Event.observers[i][0] = null; - } - Event.observers = false; - }, - - observe: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) - name = 'keydown'; - - this._observeAndCache(element, name, observer, useCapture); - }, - - stopObserving: function(element, name, observer, useCapture) { - var element = $(element); - useCapture = useCapture || false; - - if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.detachEvent)) - name = 'keydown'; - - if (element.removeEventListener) { - element.removeEventListener(name, observer, useCapture); - } else if (element.detachEvent) { - element.detachEvent('on' + name, observer); - } - } -}); - -/* prevent memory leaks in IE */ -Event.observe(window, 'unload', Event.unloadCache, false); -var Position = { - // set to true if needed, warning: firefox performance problems - // NOT neeeded for page scrolling, only if draggable contained in - // scrollable elements - includeScrollOffsets: false, - - // must be called before calling withinIncludingScrolloffset, every time the - // page is scrolled - prepare: function() { - this.deltaX = window.pageXOffset - || document.documentElement.scrollLeft - || document.body.scrollLeft - || 0; - this.deltaY = window.pageYOffset - || document.documentElement.scrollTop - || document.body.scrollTop - || 0; - }, - - realOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } while (element); - return [valueL, valueT]; - }, - - cumulativeOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - return [valueL, valueT]; - }, - - positionedOffset: function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - p = Element.getStyle(element, 'position'); - if (p == 'relative' || p == 'absolute') break; - } - } while (element); - return [valueL, valueT]; - }, - - offsetParent: function(element) { - if (element.offsetParent) return element.offsetParent; - if (element == document.body) return element; - - while ((element = element.parentNode) && element != document.body) - if (Element.getStyle(element, 'position') != 'static') - return element; - - return document.body; - }, - - // caches x/y coordinate pair to use with overlap - within: function(element, x, y) { - if (this.includeScrollOffsets) - return this.withinIncludingScrolloffsets(element, x, y); - this.xcomp = x; - this.ycomp = y; - this.offset = this.cumulativeOffset(element); - - return (y >= this.offset[1] && - y < this.offset[1] + element.offsetHeight && - x >= this.offset[0] && - x < this.offset[0] + element.offsetWidth); - }, - - withinIncludingScrolloffsets: function(element, x, y) { - var offsetcache = this.realOffset(element); - - this.xcomp = x + offsetcache[0] - this.deltaX; - this.ycomp = y + offsetcache[1] - this.deltaY; - this.offset = this.cumulativeOffset(element); - - return (this.ycomp >= this.offset[1] && - this.ycomp < this.offset[1] + element.offsetHeight && - this.xcomp >= this.offset[0] && - this.xcomp < this.offset[0] + element.offsetWidth); - }, - - // within must be called directly before - overlap: function(mode, element) { - if (!mode) return 0; - if (mode == 'vertical') - return ((this.offset[1] + element.offsetHeight) - this.ycomp) / - element.offsetHeight; - if (mode == 'horizontal') - return ((this.offset[0] + element.offsetWidth) - this.xcomp) / - element.offsetWidth; - }, - - clone: function(source, target) { - source = $(source); - target = $(target); - target.style.position = 'absolute'; - var offsets = this.cumulativeOffset(source); - target.style.top = offsets[1] + 'px'; - target.style.left = offsets[0] + 'px'; - target.style.width = source.offsetWidth + 'px'; - target.style.height = source.offsetHeight + 'px'; - }, - - page: function(forElement) { - var valueT = 0, valueL = 0; - - var element = forElement; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - - // Safari fix - if (element.offsetParent==document.body) - if (Element.getStyle(element,'position')=='absolute') break; - - } while (element = element.offsetParent); - - element = forElement; - do { - valueT -= element.scrollTop || 0; - valueL -= element.scrollLeft || 0; - } while (element = element.parentNode); - - return [valueL, valueT]; - }, - - clone: function(source, target) { - var options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, arguments[2] || {}) - - // find page position of source - source = $(source); - var p = Position.page(source); - - // find coordinate system to use - target = $(target); - var delta = [0, 0]; - var parent = null; - // delta [0,0] will do fine with position: fixed elements, - // position:absolute needs offsetParent deltas - if (Element.getStyle(target,'position') == 'absolute') { - parent = Position.offsetParent(target); - delta = Position.page(parent); - } - - // correct by body offsets (fixes Safari) - if (parent == document.body) { - delta[0] -= document.body.offsetLeft; - delta[1] -= document.body.offsetTop; - } - - // set position - if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; - if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; - if(options.setWidth) target.style.width = source.offsetWidth + 'px'; - if(options.setHeight) target.style.height = source.offsetHeight + 'px'; - }, - - absolutize: function(element) { - element = $(element); - if (element.style.position == 'absolute') return; - Position.prepare(); - - var offsets = Position.positionedOffset(element); - var top = offsets[1]; - var left = offsets[0]; - var width = element.clientWidth; - var height = element.clientHeight; - - element._originalLeft = left - parseFloat(element.style.left || 0); - element._originalTop = top - parseFloat(element.style.top || 0); - element._originalWidth = element.style.width; - element._originalHeight = element.style.height; - - element.style.position = 'absolute'; - element.style.top = top + 'px';; - element.style.left = left + 'px';; - element.style.width = width + 'px';; - element.style.height = height + 'px';; - }, - - relativize: function(element) { - element = $(element); - if (element.style.position == 'relative') return; - Position.prepare(); - - element.style.position = 'relative'; - var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); - var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); - - element.style.top = top + 'px'; - element.style.left = left + 'px'; - element.style.height = element._originalHeight; - element.style.width = element._originalWidth; - } -} - -// Safari returns margins on body which is incorrect if the child is absolutely -// positioned. For performance reasons, redefine Position.cumulativeOffset for -// KHTML/WebKit only. -if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { - Position.cumulativeOffset = function(element) { - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - if (element.offsetParent == document.body) - if (Element.getStyle(element, 'position') == 'absolute') break; - - element = element.offsetParent; - } while (element); - - return [valueL, valueT]; - } -}
\ No newline at end of file diff --git a/tests/test_tools/selenium/core/scripts/se2html.js b/tests/test_tools/selenium/core/scripts/se2html.js deleted file mode 100644 index 4894d4b1..00000000 --- a/tests/test_tools/selenium/core/scripts/se2html.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - -This is an experiment in creating a "selenese" parser that drastically -cuts down on the line noise associated with writing tests in HTML. - -The 'parse' function will accept the follow sample commands. - -test-cases: - //comment - command "param" - command "param" // comment - command "param" "param2" - command "param" "param2" // this is a comment - -TODO: -1) Deal with multiline parameters -2) Escape quotes properly -3) Determine whether this should/will become the "preferred" syntax - for delivered Selenium self-test scripts -*/ - - -function separse(doc) { - // Get object - script = doc.getElementById('testcase') - // Split into lines - lines = script.text.split('\n'); - - - var command_pattern = / *(\w+) *"([^"]*)" *(?:"([^"]*)"){0,1}(?: *(\/\/ *.+))*/i; - var comment_pattern = /^ *(\/\/ *.+)/ - - // Regex each line into selenium command and convert into table row. - // eg. "<command> <quote> <quote> <comment>" - var new_test_source = ''; - var new_line = ''; - for (var x=0; x < lines.length; x++) { - result = lines[x].match(command_pattern); - if (result != null) { - new_line = "<tr><td>" + (result[1] || ' ') + "</td>" + - "<td>" + (result[2] || ' ') + "</td>" + - "<td>" + (result[3] || ' ') + "</td>" + - "<td>" + (result[4] || ' ') + "</td></tr>\n"; - new_test_source += new_line; - } - result = lines[x].match(comment_pattern); - if (result != null) { - new_line = '<tr><td rowspan="1" colspan="4">' + - (result[1] || ' ') + - '</td></tr>'; - new_test_source += new_line; - } - } - - // Create HTML Table - body = doc.body - body.innerHTML += "<table class='selenium' id='testtable'>"+ - new_test_source + - "</table>"; - -} - - diff --git a/tests/test_tools/selenium/core/scripts/selenium-api.js b/tests/test_tools/selenium/core/scripts/selenium-api.js deleted file mode 100644 index 1646236f..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-api.js +++ /dev/null @@ -1,2329 +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. - * - */ - -// TODO: stop navigating this.browserbot.document() ... it breaks encapsulation - -var storedVars = new Object(); - -function Selenium(browserbot) { - /** - * Defines an object that runs Selenium commands. - * - * <h3><a name="locators"></a>Element Locators</h3> - * <p> - * Element Locators tell Selenium which HTML element a command refers to. - * The format of a locator is:</p> - * <blockquote> - * <em>locatorType</em><strong>=</strong><em>argument</em> - * </blockquote> - * - * <p> - * We support the following strategies for locating elements: - * </p> - * - * <ul> - * <li><strong>identifier</strong>=<em>id</em>: - * Select the element with the specified @id attribute. If no match is - * found, select the first element whose @name attribute is <em>id</em>. - * (This is normally the default; see below.)</li> - * <li><strong>id</strong>=<em>id</em>: - * Select the element with the specified @id attribute.</li> - * - * <li><strong>name</strong>=<em>name</em>: - * Select the first element with the specified @name attribute. - * <ul class="first last simple"> - * <li>username</li> - * <li>name=username</li> - * </ul> - * - * <p>The name may optionally be followed by one or more <em>element-filters</em>, separated from the name by whitespace. If the <em>filterType</em> is not specified, <strong>value</strong> is assumed.</p> - * - * <ul class="first last simple"> - * <li>name=flavour value=chocolate</li> - * </ul> - * </li> - * <li><strong>dom</strong>=<em>javascriptExpression</em>: - * - * Find an element by evaluating the specified string. This allows you to traverse the HTML Document Object - * Model using JavaScript. Note that you must not return a value in this string; simply make it the last expression in the block. - * <ul class="first last simple"> - * <li>dom=document.forms['myForm'].myDropdown</li> - * <li>dom=document.images[56]</li> - * <li>dom=function foo() { return document.links[1]; }; foo();</li> - * </ul> - * - * </li> - * - * <li><strong>xpath</strong>=<em>xpathExpression</em>: - * Locate an element using an XPath expression. - * <ul class="first last simple"> - * <li>xpath=//img[@alt='The image alt text']</li> - * <li>xpath=//table[@id='table1']//tr[4]/td[2]</li> - * <li>xpath=//a[contains(@href,'#id1')]</li> - * <li>xpath=//a[contains(@href,'#id1')]/@class</li> - * <li>xpath=(//table[@class='stylee'])//th[text()='theHeaderText']/../td</li> - * <li>xpath=//input[@name='name2' and @value='yes']</li> - * <li>xpath=//*[text()="right"]</li> - * - * </ul> - * </li> - * <li><strong>link</strong>=<em>textPattern</em>: - * Select the link (anchor) element which contains text matching the - * specified <em>pattern</em>. - * <ul class="first last simple"> - * <li>link=The link text</li> - * </ul> - * - * </li> - * - * <li><strong>css</strong>=<em>cssSelectorSyntax</em>: - * Select the element using css selectors. Please refer to <a href="http://www.w3.org/TR/REC-CSS2/selector.html">CSS2 selectors</a>, <a href="http://www.w3.org/TR/2001/CR-css3-selectors-20011113/">CSS3 selectors</a> for more information. You can also check the TestCssLocators test in the selenium test suite for an example of usage, which is included in the downloaded selenium core package. - * <ul class="first last simple"> - * <li>css=a[href="#id3"]</li> - * <li>css=span#firstChild + span</li> - * </ul> - * <p>Currently the css selector locator supports all css1, css2 and css3 selectors except namespace in css3, some pseudo classes(:nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type, :only-of-type, :visited, :hover, :active, :focus, :indeterminate) and pseudo elements(::first-line, ::first-letter, ::selection, ::before, ::after). </p> - * </li> - * </ul> - * - * <p> - * Without an explicit locator prefix, Selenium uses the following default - * strategies: - * </p> - * - * <ul class="simple"> - * <li><strong>dom</strong>, for locators starting with "document."</li> - * <li><strong>xpath</strong>, for locators starting with "//"</li> - * <li><strong>identifier</strong>, otherwise</li> - * </ul> - * - * <h3><a name="element-filters">Element Filters</a></h3> - * <blockquote> - * <p>Element filters can be used with a locator to refine a list of candidate elements. They are currently used only in the 'name' element-locator.</p> - * <p>Filters look much like locators, ie.</p> - * <blockquote> - * <em>filterType</em><strong>=</strong><em>argument</em></blockquote> - * - * <p>Supported element-filters are:</p> - * <p><strong>value=</strong><em>valuePattern</em></p> - * <blockquote> - * Matches elements based on their values. This is particularly useful for refining a list of similarly-named toggle-buttons.</blockquote> - * <p><strong>index=</strong><em>index</em></p> - * <blockquote> - * Selects a single element based on its position in the list (offset from zero).</blockquote> - * </blockquote> - * - * <h3><a name="patterns"></a>String-match Patterns</h3> - * - * <p> - * Various Pattern syntaxes are available for matching string values: - * </p> - * <ul> - * <li><strong>glob:</strong><em>pattern</em>: - * Match a string against a "glob" (aka "wildmat") pattern. "Glob" is a - * kind of limited regular-expression syntax typically used in command-line - * shells. In a glob pattern, "*" represents any sequence of characters, and "?" - * represents any single character. Glob patterns match against the entire - * string.</li> - * <li><strong>regexp:</strong><em>regexp</em>: - * Match a string using a regular-expression. The full power of JavaScript - * regular-expressions is available.</li> - * <li><strong>exact:</strong><em>string</em>: - * - * Match a string exactly, verbatim, without any of that fancy wildcard - * stuff.</li> - * </ul> - * <p> - * If no pattern prefix is specified, Selenium assumes that it's a "glob" - * pattern. - * </p> - */ - this.browserbot = browserbot; - this.optionLocatorFactory = new OptionLocatorFactory(); - // DGF for backwards compatibility - this.page = function() { - return browserbot; - }; - this.defaultTimeout = Selenium.DEFAULT_TIMEOUT; - this.mouseSpeed = 10; -} - -Selenium.DEFAULT_TIMEOUT = 30 * 1000; -Selenium.DEFAULT_MOUSE_SPEED = 10; - -Selenium.decorateFunctionWithTimeout = function(f, timeout) { - if (f == null) { - return null; - } - var timeoutValue = parseInt(timeout); - if (isNaN(timeoutValue)) { - throw new SeleniumError("Timeout is not a number: '" + timeout + "'"); - } - var now = new Date().getTime(); - var timeoutTime = now + timeoutValue; - return function() { - if (new Date().getTime() > timeoutTime) { - throw new SeleniumError("Timed out after " + timeoutValue + "ms"); - } - return f(); - }; -} - -Selenium.createForWindow = function(window, proxyInjectionMode) { - if (!window.location) { - throw "error: not a window!"; - } - return new Selenium(BrowserBot.createForWindow(window, proxyInjectionMode)); -}; - -Selenium.prototype.reset = function() { - this.defaultTimeout = Selenium.DEFAULT_TIMEOUT; - // todo: this.browserbot.reset() - this.browserbot.selectWindow("null"); - this.browserbot.resetPopups(); -}; - -Selenium.prototype.doClick = function(locator) { - /** - * Clicks on a link, button, checkbox or radio button. If the click action - * causes a new page to load (like a link usually does), call - * waitForPageToLoad. - * - * @param locator an element locator - * - */ - var element = this.browserbot.findElement(locator); - this.browserbot.clickElement(element); -}; - -Selenium.prototype.doDoubleClick = function(locator) { - /** - * Double clicks on a link, button, checkbox or radio button. If the double click action - * causes a new page to load (like a link usually does), call - * waitForPageToLoad. - * - * @param locator an element locator - * - */ - var element = this.browserbot.findElement(locator); - this.browserbot.doubleClickElement(element); -}; - -Selenium.prototype.doClickAt = function(locator, coordString) { - /** - * Clicks on a link, button, checkbox or radio button. If the click action - * causes a new page to load (like a link usually does), call - * waitForPageToLoad. - * - * @param locator an element locator - * @param coordString specifies the x,y position (i.e. - 10,20) of the mouse - * event relative to the element returned by the locator. - * - */ - var element = this.browserbot.findElement(locator); - var clientXY = getClientXY(element, coordString) - this.browserbot.clickElement(element, clientXY[0], clientXY[1]); -}; - -Selenium.prototype.doDoubleClickAt = function(locator, coordString) { - /** - * Doubleclicks on a link, button, checkbox or radio button. If the action - * causes a new page to load (like a link usually does), call - * waitForPageToLoad. - * - * @param locator an element locator - * @param coordString specifies the x,y position (i.e. - 10,20) of the mouse - * event relative to the element returned by the locator. - * - */ - var element = this.browserbot.findElement(locator); - var clientXY = getClientXY(element, coordString) - this.browserbot.doubleClickElement(element, clientXY[0], clientXY[1]); -}; - -Selenium.prototype.doFireEvent = function(locator, eventName) { - /** - * Explicitly simulate an event, to trigger the corresponding "on<em>event</em>" - * handler. - * - * @param locator an <a href="#locators">element locator</a> - * @param eventName the event name, e.g. "focus" or "blur" - */ - var element = this.browserbot.findElement(locator); - triggerEvent(element, eventName, false); -}; - -Selenium.prototype.doKeyPress = function(locator, keySequence) { - /** - * Simulates a user pressing and releasing a key. - * - * @param locator an <a href="#locators">element locator</a> - * @param keySequence Either be a string("\" followed by the numeric keycode - * of the key to be pressed, normally the ASCII value of that key), or a single - * character. For example: "w", "\119". - */ - var element = this.browserbot.findElement(locator); - triggerKeyEvent(element, 'keypress', keySequence, true, - this.browserbot.controlKeyDown, - this.browserbot.altKeyDown, - this.browserbot.shiftKeyDown, - this.browserbot.metaKeyDown); -}; - -Selenium.prototype.doShiftKeyDown = function() { - /** - * Press the shift key and hold it down until doShiftUp() is called or a new page is loaded. - * - */ - this.browserbot.shiftKeyDown = true; -}; - -Selenium.prototype.doShiftKeyUp = function() { - /** - * Release the shift key. - * - */ - this.browserbot.shiftKeyDown = false; -}; - -Selenium.prototype.doMetaKeyDown = function() { - /** - * Press the meta key and hold it down until doMetaUp() is called or a new page is loaded. - * - */ - this.browserbot.metaKeyDown = true; -}; - -Selenium.prototype.doMetaKeyUp = function() { - /** - * Release the meta key. - * - */ - this.browserbot.metaKeyDown = false; -}; - -Selenium.prototype.doAltKeyDown = function() { - /** - * Press the alt key and hold it down until doAltUp() is called or a new page is loaded. - * - */ - this.browserbot.altKeyDown = true; -}; - -Selenium.prototype.doAltKeyUp = function() { - /** - * Release the alt key. - * - */ - this.browserbot.altKeyDown = false; -}; - -Selenium.prototype.doControlKeyDown = function() { - /** - * Press the control key and hold it down until doControlUp() is called or a new page is loaded. - * - */ - this.browserbot.controlKeyDown = true; -}; - -Selenium.prototype.doControlKeyUp = function() { - /** - * Release the control key. - * - */ - this.browserbot.controlKeyDown = false; -}; - -Selenium.prototype.doKeyDown = function(locator, keySequence) { - /** - * Simulates a user pressing a key (without releasing it yet). - * - * @param locator an <a href="#locators">element locator</a> - * @param keySequence Either be a string("\" followed by the numeric keycode - * of the key to be pressed, normally the ASCII value of that key), or a single - * character. For example: "w", "\119". - */ - var element = this.browserbot.findElement(locator); - triggerKeyEvent(element, 'keydown', keySequence, true, - this.browserbot.controlKeyDown, - this.browserbot.altKeyDown, - this.browserbot.shiftKeyDown, - this.browserbot.metaKeyDown); -}; - -Selenium.prototype.doKeyUp = function(locator, keySequence) { - /** - * Simulates a user releasing a key. - * - * @param locator an <a href="#locators">element locator</a> - * @param keySequence Either be a string("\" followed by the numeric keycode - * of the key to be pressed, normally the ASCII value of that key), or a single - * character. For example: "w", "\119". - */ - var element = this.browserbot.findElement(locator); - triggerKeyEvent(element, 'keyup', keySequence, true, - this.browserbot.controlKeyDown, - this.browserbot.altKeyDown, - this.browserbot.shiftKeyDown, - this.browserbot.metaKeyDown); -}; - -function getClientXY(element, coordString) { - // Parse coordString - var coords = null; - var x; - var y; - if (coordString) { - coords = coordString.split(/,/); - x = Number(coords[0]); - y = Number(coords[1]); - } - else { - x = y = 0; - } - - // Get position of element, - // Return 2 item array with clientX and clientY - return [Selenium.prototype.getElementPositionLeft(element) + x, Selenium.prototype.getElementPositionTop(element) + y]; -} - -Selenium.prototype.doMouseOver = function(locator) { - /** - * Simulates a user hovering a mouse over the specified element. - * - * @param locator an <a href="#locators">element locator</a> - */ - var element = this.browserbot.findElement(locator); - this.browserbot.triggerMouseEvent(element, 'mouseover', true); -}; - -Selenium.prototype.doMouseOut = function(locator) { - /** - * Simulates a user moving the mouse pointer away from the specified element. - * - * @param locator an <a href="#locators">element locator</a> - */ - var element = this.browserbot.findElement(locator); - this.browserbot.triggerMouseEvent(element, 'mouseout', true); -}; - -Selenium.prototype.doMouseDown = function(locator) { - /** - * Simulates a user pressing the mouse button (without releasing it yet) on - * the specified element. - * - * @param locator an <a href="#locators">element locator</a> - */ - var element = this.browserbot.findElement(locator); - this.browserbot.triggerMouseEvent(element, 'mousedown', true); -}; - -Selenium.prototype.doMouseDownAt = function(locator, coordString) { - /** - * Simulates a user pressing the mouse button (without releasing it yet) on - * the specified element. - * - * @param locator an <a href="#locators">element locator</a> - * @param coordString specifies the x,y position (i.e. - 10,20) of the mouse - * event relative to the element returned by the locator. - */ - var element = this.browserbot.findElement(locator); - var clientXY = getClientXY(element, coordString) - - this.browserbot.triggerMouseEvent(element, 'mousedown', true, clientXY[0], clientXY[1]); -}; - -Selenium.prototype.doMouseUp = function(locator) { - /** - * Simulates a user pressing the mouse button (without releasing it yet) on - * the specified element. - * - * @param locator an <a href="#locators">element locator</a> - */ - var element = this.browserbot.findElement(locator); - this.browserbot.triggerMouseEvent(element, 'mouseup', true); -}; - -Selenium.prototype.doMouseUpAt = function(locator, coordString) { - /** - * Simulates a user pressing the mouse button (without releasing it yet) on - * the specified element. - * - * @param locator an <a href="#locators">element locator</a> - * @param coordString specifies the x,y position (i.e. - 10,20) of the mouse - * event relative to the element returned by the locator. - */ - var element = this.browserbot.findElement(locator); - var clientXY = getClientXY(element, coordString) - - this.browserbot.triggerMouseEvent(element, 'mouseup', true, clientXY[0], clientXY[1]); -}; - -Selenium.prototype.doMouseMove = function(locator) { - /** - * Simulates a user pressing the mouse button (without releasing it yet) on - * the specified element. - * - * @param locator an <a href="#locators">element locator</a> - */ - var element = this.browserbot.findElement(locator); - this.browserbot.triggerMouseEvent(element, 'mousemove', true); -}; - -Selenium.prototype.doMouseMoveAt = function(locator, coordString) { - /** - * Simulates a user pressing the mouse button (without releasing it yet) on - * the specified element. - * - * @param locator an <a href="#locators">element locator</a> - * @param coordString specifies the x,y position (i.e. - 10,20) of the mouse - * event relative to the element returned by the locator. - */ - - var element = this.browserbot.findElement(locator); - var clientXY = getClientXY(element, coordString) - - this.browserbot.triggerMouseEvent(element, 'mousemove', true, clientXY[0], clientXY[1]); -}; - -Selenium.prototype.doType = function(locator, value) { - /** - * Sets the value of an input field, as though you typed it in. - * - * <p>Can also be used to set the value of combo boxes, check boxes, etc. In these cases, - * value should be the value of the option selected, not the visible text.</p> - * - * @param locator an <a href="#locators">element locator</a> - * @param value the value to type - */ - if (this.browserbot.controlKeyDown || this.browserbot.altKeyDown || this.browserbot.metaKeyDown) { - throw new SeleniumError("type not supported immediately after call to controlKeyDown() or altKeyDown() or metaKeyDown()"); - } - // TODO fail if it can't be typed into. - var element = this.browserbot.findElement(locator); - if (this.browserbot.shiftKeyDown) { - value = new String(value).toUpperCase(); - } - this.browserbot.replaceText(element, value); -}; - -Selenium.prototype.doTypeKeys = function(locator, value) { - /** - * Simulates keystroke events on the specified element, as though you typed the value key-by-key. - * - * <p>This is a convenience method for calling keyDown, keyUp, keyPress for every character in the specified string; - * this is useful for dynamic UI widgets (like auto-completing combo boxes) that require explicit key events.</p> - * - * <p>Unlike the simple "type" command, which forces the specified value into the page directly, this command - * may or may not have any visible effect, even in cases where typing keys would normally have a visible effect. - * For example, if you use "typeKeys" on a form element, you may or may not see the results of what you typed in - * the field.</p> - * <p>In some cases, you may need to use the simple "type" command to set the value of the field and then the "typeKeys" command to - * send the keystroke events corresponding to what you just typed.</p> - * - * @param locator an <a href="#locators">element locator</a> - * @param value the value to type - */ - var keys = new String(value).split(""); - for (var i = 0; i < keys.length; i++) { - var c = keys[i]; - this.doKeyDown(locator, c); - this.doKeyUp(locator, c); - this.doKeyPress(locator, c); - } -}; - -Selenium.prototype.doSetSpeed = function(value) { - /** - * Set execution speed (i.e., set the millisecond length of a delay which will follow each selenium operation). By default, there is no such delay, i.e., - * the delay is 0 milliseconds. - * - * @param value the number of milliseconds to pause after operation - */ - throw new SeleniumError("this operation is only implemented in selenium-rc, and should never result in a request making it across the wire"); -}; - -Selenium.prototype.doGetSpeed = function() { - /** - * Get execution speed (i.e., get the millisecond length of the delay following each selenium operation). By default, there is no such delay, i.e., - * the delay is 0 milliseconds. - * - * See also setSpeed. - */ - throw new SeleniumError("this operation is only implemented in selenium-rc, and should never result in a request making it across the wire"); -}; - -Selenium.prototype.findToggleButton = function(locator) { - var element = this.browserbot.findElement(locator); - if (element.checked == null) { - Assert.fail("Element " + locator + " is not a toggle-button."); - } - return element; -} - -Selenium.prototype.doCheck = function(locator) { - /** - * Check a toggle-button (checkbox/radio) - * - * @param locator an <a href="#locators">element locator</a> - */ - this.findToggleButton(locator).checked = true; -}; - -Selenium.prototype.doUncheck = function(locator) { - /** - * Uncheck a toggle-button (checkbox/radio) - * - * @param locator an <a href="#locators">element locator</a> - */ - this.findToggleButton(locator).checked = false; -}; - -Selenium.prototype.doSelect = function(selectLocator, optionLocator) { - /** - * Select an option from a drop-down using an option locator. - * - * <p> - * Option locators provide different ways of specifying options of an HTML - * Select element (e.g. for selecting a specific option, or for asserting - * that the selected option satisfies a specification). There are several - * forms of Select Option Locator. - * </p> - * <ul> - * <li><strong>label</strong>=<em>labelPattern</em>: - * matches options based on their labels, i.e. the visible text. (This - * is the default.) - * <ul class="first last simple"> - * <li>label=regexp:^[Oo]ther</li> - * </ul> - * </li> - * <li><strong>value</strong>=<em>valuePattern</em>: - * matches options based on their values. - * <ul class="first last simple"> - * <li>value=other</li> - * </ul> - * - * - * </li> - * <li><strong>id</strong>=<em>id</em>: - * - * matches options based on their ids. - * <ul class="first last simple"> - * <li>id=option1</li> - * </ul> - * </li> - * <li><strong>index</strong>=<em>index</em>: - * matches an option based on its index (offset from zero). - * <ul class="first last simple"> - * - * <li>index=2</li> - * </ul> - * </li> - * </ul> - * <p> - * If no option locator prefix is provided, the default behaviour is to match on <strong>label</strong>. - * </p> - * - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @param optionLocator an option locator (a label by default) - */ - var element = this.browserbot.findElement(selectLocator); - if (!("options" in element)) { - throw new SeleniumError("Specified element is not a Select (has no options)"); - } - var locator = this.optionLocatorFactory.fromLocatorString(optionLocator); - var option = locator.findOption(element); - this.browserbot.selectOption(element, option); -}; - - - -Selenium.prototype.doAddSelection = function(locator, optionLocator) { - /** - * Add a selection to the set of selected options in a multi-select element using an option locator. - * - * @see #doSelect for details of option locators - * - * @param locator an <a href="#locators">element locator</a> identifying a multi-select box - * @param optionLocator an option locator (a label by default) - */ - var element = this.browserbot.findElement(locator); - if (!("options" in element)) { - throw new SeleniumError("Specified element is not a Select (has no options)"); - } - var locator = this.optionLocatorFactory.fromLocatorString(optionLocator); - var option = locator.findOption(element); - this.browserbot.addSelection(element, option); -}; - -Selenium.prototype.doRemoveSelection = function(locator, optionLocator) { - /** - * Remove a selection from the set of selected options in a multi-select element using an option locator. - * - * @see #doSelect for details of option locators - * - * @param locator an <a href="#locators">element locator</a> identifying a multi-select box - * @param optionLocator an option locator (a label by default) - */ - - var element = this.browserbot.findElement(locator); - if (!("options" in element)) { - throw new SeleniumError("Specified element is not a Select (has no options)"); - } - var locator = this.optionLocatorFactory.fromLocatorString(optionLocator); - var option = locator.findOption(element); - this.browserbot.removeSelection(element, option); -}; - -Selenium.prototype.doRemoveAllSelections = function(locator) { - /** - * Unselects all of the selected options in a multi-select element. - * - * @param locator an <a href="#locators">element locator</a> identifying a multi-select box - */ - var element = this.browserbot.findElement(locator); - if (!("options" in element)) { - throw new SeleniumError("Specified element is not a Select (has no options)"); - } - for (var i = 0; i < element.options.length; i++) { - this.browserbot.removeSelection(element, element.options[i]); - } -} - -Selenium.prototype.doSubmit = function(formLocator) { - /** - * Submit the specified form. This is particularly useful for forms without - * submit buttons, e.g. single-input "Search" forms. - * - * @param formLocator an <a href="#locators">element locator</a> for the form you want to submit - */ - var form = this.browserbot.findElement(formLocator); - return this.browserbot.submit(form); - -}; - -Selenium.prototype.makePageLoadCondition = function(timeout) { - if (timeout == null) { - timeout = this.defaultTimeout; - } - return Selenium.decorateFunctionWithTimeout(fnBind(this._isNewPageLoaded, this), timeout); -}; - -Selenium.prototype.doOpen = function(url) { - /** - * Opens an URL in the test frame. This accepts both relative and absolute - * URLs. - * - * The "open" command waits for the page to load before proceeding, - * ie. the "AndWait" suffix is implicit. - * - * <em>Note</em>: The URL must be on the same domain as the runner HTML - * due to security restrictions in the browser (Same Origin Policy). If you - * need to open an URL on another domain, use the Selenium Server to start a - * new browser session on that domain. - * - * @param url the URL to open; may be relative or absolute - */ - this.browserbot.openLocation(url); - return this.makePageLoadCondition(); -}; - -Selenium.prototype.doOpenWindow = function(url, windowID) { - /** - * Opens a popup window (if a window with that ID isn't already open). - * After opening the window, you'll need to select it using the selectWindow - * command. - * - * <p>This command can also be a useful workaround for bug SEL-339. In some cases, Selenium will be unable to intercept a call to window.open (if the call occurs during or before the "onLoad" event, for example). - * In those cases, you can force Selenium to notice the open window's name by using the Selenium openWindow command, using - * an empty (blank) url, like this: openWindow("", "myFunnyWindow").</p> - * - * @param url the URL to open, which can be blank - * @param windowID the JavaScript window ID of the window to select - */ - this.browserbot.openWindow(url, windowID); -}; - -Selenium.prototype.doSelectWindow = function(windowID) { - /** - * Selects a popup window; once a popup window has been selected, all - * commands go to that window. To select the main window again, use null - * as the target. - * - * <p>Selenium has several strategies for finding the window object referred to by the "windowID" parameter.</p> - * - * <p>1.) if windowID is null, then it is assumed the user is referring to the original window instantiated by the browser).</p> - * <p>2.) if the value of the "windowID" parameter is a JavaScript variable name in the current application window, then it is assumed - * that this variable contains the return value from a call to the JavaScript window.open() method.</p> - * <p>3.) Otherwise, selenium looks in a hash it maintains that maps string names to window objects. Each of these string - * names matches the second parameter "windowName" past to the JavaScript method window.open(url, windowName, windowFeatures, replaceFlag) - * (which selenium intercepts).</p> - * - * <p>If you're having trouble figuring out what is the name of a window that you want to manipulate, look at the selenium log messages - * which identify the names of windows created via window.open (and therefore intercepted by selenium). You will see messages - * like the following for each window as it is opened:</p> - * - * <p><code>debug: window.open call intercepted; window ID (which you can use with selectWindow()) is "myNewWindow"</code></p> - * - * <p>In some cases, Selenium will be unable to intercept a call to window.open (if the call occurs during or before the "onLoad" event, for example). - * (This is bug SEL-339.) In those cases, you can force Selenium to notice the open window's name by using the Selenium openWindow command, using - * an empty (blank) url, like this: openWindow("", "myFunnyWindow").</p> - * - * @param windowID the JavaScript window ID of the window to select - */ - this.browserbot.selectWindow(windowID); -}; - -Selenium.prototype.doSelectFrame = function(locator) { - /** - * Selects a frame within the current window. (You may invoke this command - * multiple times to select nested frames.) To select the parent frame, use - * "relative=parent" as a locator; to select the top frame, use "relative=top". - * - * <p>You may also use a DOM expression to identify the frame you want directly, - * like this: <code>dom=frames["main"].frames["subframe"]</code></p> - * - * @param locator an <a href="#locators">element locator</a> identifying a frame or iframe - */ - this.browserbot.selectFrame(locator); -}; - -Selenium.prototype.getLogMessages = function() { - /** - * Return the contents of the log. - * - * <p>This is a placeholder intended to make the code generator make this API - * available to clients. The selenium server will intercept this call, however, - * and return its recordkeeping of log messages since the last call to this API. - * Thus this code in JavaScript will never be called.</p> - * - * <p>The reason I opted for a servercentric solution is to be able to support - * multiple frames served from different domains, which would break a - * centralized JavaScript logging mechanism under some conditions.</p> - * - * @return string all log messages seen since the last call to this API - */ - return "getLogMessages should be implemented in the selenium server"; -}; - - -Selenium.prototype.getWhetherThisFrameMatchFrameExpression = function(currentFrameString, target) { - /** - * Determine whether current/locator identify the frame containing this running code. - * - * <p>This is useful in proxy injection mode, where this code runs in every - * browser frame and window, and sometimes the selenium server needs to identify - * the "current" frame. In this case, when the test calls selectFrame, this - * routine is called for each frame to figure out which one has been selected. - * The selected frame will return true, while all others will return false.</p> - * - * @param currentFrameString starting frame - * @param target new frame (which might be relative to the current one) - * @return boolean true if the new frame is this code's window - */ - var isDom = false; - if (target.indexOf("dom=") == 0) { - target = target.substr(4); - isDom = true; - } - var t; - try { - eval("t=" + currentFrameString + "." + target); - } catch (e) { - } - var autWindow = this.browserbot.getCurrentWindow(); - if (t != null) { - if (t.window == autWindow) { - return true; - } - return false; - } - if (isDom) { - return false; - } - var currentFrame; - eval("currentFrame=" + currentFrameString); - if (target == "relative=up") { - if (currentFrame.window.parent == autWindow) { - return true; - } - return false; - } - if (target == "relative=top") { - if (currentFrame.window.top == autWindow) { - return true; - } - return false; - } - if (autWindow.name == target && currentFrame.window == autWindow.parent) { - return true; - } - return false; -}; - -Selenium.prototype.getWhetherThisWindowMatchWindowExpression = function(currentWindowString, target) { - /** - * Determine whether currentWindowString plus target identify the window containing this running code. - * - * <p>This is useful in proxy injection mode, where this code runs in every - * browser frame and window, and sometimes the selenium server needs to identify - * the "current" window. In this case, when the test calls selectWindow, this - * routine is called for each window to figure out which one has been selected. - * The selected window will return true, while all others will return false.</p> - * - * @param currentWindowString starting window - * @param target new window (which might be relative to the current one, e.g., "_parent") - * @return boolean true if the new window is this code's window - */ - if (window.opener!=null && window.opener[target]!=null && window.opener[target]==window) { - return true; - } - return false; -}; - -Selenium.prototype.doWaitForPopUp = function(windowID, timeout) { - /** - * Waits for a popup window to appear and load up. - * - * @param windowID the JavaScript window ID of the window that will appear - * @param timeout a timeout in milliseconds, after which the action will return with an error - */ - var popupLoadedPredicate = function () { - var targetWindow = selenium.browserbot.getWindowByName(windowID, true); - if (!targetWindow) return false; - if (!targetWindow.location) return false; - if ("about:blank" == targetWindow.location) return false; - if (browserVersion.isKonqueror) { - if ("/" == targetWindow.location.href) { - // apparently Konqueror uses this as the temporary location, instead of about:blank - return false; - } - } - if (browserVersion.isSafari) { - if(targetWindow.location.href == selenium.browserbot.buttonWindow.location.href) { - // Apparently Safari uses this as the temporary location, instead of about:blank - // what a world! - LOG.debug("DGF what a world!"); - return false; - } - } - if (!targetWindow.document) return false; - if (!selenium.browserbot.getCurrentWindow().document.readyState) { - // This is Firefox, with no readyState extension - return true; - } - if ('complete' != targetWindow.document.readyState) return false; - return true; - }; - - return Selenium.decorateFunctionWithTimeout(popupLoadedPredicate, timeout); -} - -Selenium.prototype.doWaitForPopUp.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.doChooseCancelOnNextConfirmation = function() { - /** - * By default, Selenium's overridden window.confirm() function will - * return true, as if the user had manually clicked OK. After running - * this command, the next call to confirm() will return false, as if - * the user had clicked Cancel. - * - */ - this.browserbot.cancelNextConfirmation(); -}; - - -Selenium.prototype.doAnswerOnNextPrompt = function(answer) { - /** - * Instructs Selenium to return the specified answer string in response to - * the next JavaScript prompt [window.prompt()]. - * - * - * @param answer the answer to give in response to the prompt pop-up - */ - this.browserbot.setNextPromptResult(answer); -}; - -Selenium.prototype.doGoBack = function() { - /** - * Simulates the user clicking the "back" button on their browser. - * - */ - this.browserbot.goBack(); -}; - -Selenium.prototype.doRefresh = function() { - /** - * Simulates the user clicking the "Refresh" button on their browser. - * - */ - this.browserbot.refresh(); -}; - -Selenium.prototype.doClose = function() { - /** - * Simulates the user clicking the "close" button in the titlebar of a popup - * window or tab. - */ - this.browserbot.close(); -}; - -Selenium.prototype.ensureNoUnhandledPopups = function() { - if (this.browserbot.hasAlerts()) { - throw new SeleniumError("There was an unexpected Alert! [" + this.browserbot.getNextAlert() + "]"); - } - if ( this.browserbot.hasConfirmations() ) { - throw new SeleniumError("There was an unexpected Confirmation! [" + this.browserbot.getNextConfirmation() + "]"); - } -}; - -Selenium.prototype.isAlertPresent = function() { - /** - * Has an alert occurred? - * - * <p> - * This function never throws an exception - * </p> - * @return boolean true if there is an alert - */ - return this.browserbot.hasAlerts(); -}; - -Selenium.prototype.isPromptPresent = function() { - /** - * Has a prompt occurred? - * - * <p> - * This function never throws an exception - * </p> - * @return boolean true if there is a pending prompt - */ - return this.browserbot.hasPrompts(); -}; - -Selenium.prototype.isConfirmationPresent = function() { - /** - * Has confirm() been called? - * - * <p> - * This function never throws an exception - * </p> - * @return boolean true if there is a pending confirmation - */ - return this.browserbot.hasConfirmations(); -}; -Selenium.prototype.getAlert = function() { - /** - * Retrieves the message of a JavaScript alert generated during the previous action, or fail if there were no alerts. - * - * <p>Getting an alert has the same effect as manually clicking OK. If an - * alert is generated but you do not get/verify it, the next Selenium action - * will fail.</p> - * - * <p>NOTE: under Selenium, JavaScript alerts will NOT pop up a visible alert - * dialog.</p> - * - * <p>NOTE: Selenium does NOT support JavaScript alerts that are generated in a - * page's onload() event handler. In this case a visible dialog WILL be - * generated and Selenium will hang until someone manually clicks OK.</p> - * @return string The message of the most recent JavaScript alert - */ - if (!this.browserbot.hasAlerts()) { - Assert.fail("There were no alerts"); - } - return this.browserbot.getNextAlert(); -}; -Selenium.prototype.getAlert.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.getConfirmation = function() { - /** - * Retrieves the message of a JavaScript confirmation dialog generated during - * the previous action. - * - * <p> - * By default, the confirm function will return true, having the same effect - * as manually clicking OK. This can be changed by prior execution of the - * chooseCancelOnNextConfirmation command. If an confirmation is generated - * but you do not get/verify it, the next Selenium action will fail. - * </p> - * - * <p> - * NOTE: under Selenium, JavaScript confirmations will NOT pop up a visible - * dialog. - * </p> - * - * <p> - * NOTE: Selenium does NOT support JavaScript confirmations that are - * generated in a page's onload() event handler. In this case a visible - * dialog WILL be generated and Selenium will hang until you manually click - * OK. - * </p> - * - * @return string the message of the most recent JavaScript confirmation dialog - */ - if (!this.browserbot.hasConfirmations()) { - Assert.fail("There were no confirmations"); - } - return this.browserbot.getNextConfirmation(); -}; -Selenium.prototype.getConfirmation.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.getPrompt = function() { - /** - * Retrieves the message of a JavaScript question prompt dialog generated during - * the previous action. - * - * <p>Successful handling of the prompt requires prior execution of the - * answerOnNextPrompt command. If a prompt is generated but you - * do not get/verify it, the next Selenium action will fail.</p> - * - * <p>NOTE: under Selenium, JavaScript prompts will NOT pop up a visible - * dialog.</p> - * - * <p>NOTE: Selenium does NOT support JavaScript prompts that are generated in a - * page's onload() event handler. In this case a visible dialog WILL be - * generated and Selenium will hang until someone manually clicks OK.</p> - * @return string the message of the most recent JavaScript question prompt - */ - if (! this.browserbot.hasPrompts()) { - Assert.fail("There were no prompts"); - } - return this.browserbot.getNextPrompt(); -}; - -Selenium.prototype.getLocation = function() { - /** Gets the absolute URL of the current page. - * - * @return string the absolute URL of the current page - */ - return this.browserbot.getCurrentWindow().location; -}; - -Selenium.prototype.getTitle = function() { - /** Gets the title of the current page. - * - * @return string the title of the current page - */ - return this.browserbot.getTitle(); -}; - - -Selenium.prototype.getBodyText = function() { - /** - * Gets the entire text of the page. - * @return string the entire text of the page - */ - return this.browserbot.bodyText(); -}; - - -Selenium.prototype.getValue = function(locator) { - /** - * Gets the (whitespace-trimmed) value of an input field (or anything else with a value parameter). - * For checkbox/radio elements, the value will be "on" or "off" depending on - * whether the element is checked or not. - * - * @param locator an <a href="#locators">element locator</a> - * @return string the element value, or "on/off" for checkbox/radio elements - */ - var element = this.browserbot.findElement(locator) - return getInputValue(element).trim(); -} - -Selenium.prototype.getText = function(locator) { - /** - * Gets the text of an element. This works for any element that contains - * text. This command uses either the textContent (Mozilla-like browsers) or - * the innerText (IE-like browsers) of the element, which is the rendered - * text shown to the user. - * - * @param locator an <a href="#locators">element locator</a> - * @return string the text of the element - */ - var element = this.browserbot.findElement(locator); - return getText(element).trim(); -}; - -Selenium.prototype.doHighlight = function(locator) { - /** - * Briefly changes the backgroundColor of the specified element yellow. Useful for debugging. - * - * @param locator an <a href="#locators">element locator</a> - */ - var element = this.browserbot.findElement(locator); - this.browserbot.highlight(element, true); -}; - -Selenium.prototype.getEval = function(script) { - /** Gets the result of evaluating the specified JavaScript snippet. The snippet may - * have multiple lines, but only the result of the last line will be returned. - * - * <p>Note that, by default, the snippet will run in the context of the "selenium" - * object itself, so <code>this</code> will refer to the Selenium object, and <code>window</code> will - * refer to the top-level runner test window, not the window of your application.</p> - * - * <p>If you need a reference to the window of your application, you can refer - * to <code>this.browserbot.getCurrentWindow()</code> and if you need to use - * a locator to refer to a single element in your application page, you can - * use <code>this.browserbot.findElement("foo")</code> where "foo" is your locator.</p> - * - * @param script the JavaScript snippet to run - * @return string the results of evaluating the snippet - */ - try { - var result = eval(script); - // Selenium RC doesn't allow returning null - if (null == result) return "null"; - return result; - } catch (e) { - throw new SeleniumError("Threw an exception: " + e.message); - } -}; - -Selenium.prototype.isChecked = function(locator) { - /** - * Gets whether a toggle-button (checkbox/radio) is checked. Fails if the specified element doesn't exist or isn't a toggle-button. - * @param locator an <a href="#locators">element locator</a> pointing to a checkbox or radio button - * @return boolean true if the checkbox is checked, false otherwise - */ - var element = this.browserbot.findElement(locator); - if (element.checked == null) { - throw new SeleniumError("Element " + locator + " is not a toggle-button."); - } - return element.checked; -}; - -Selenium.prototype.getTable = function(tableCellAddress) { - /** - * Gets the text from a cell of a table. The cellAddress syntax - * tableLocator.row.column, where row and column start at 0. - * - * @param tableCellAddress a cell address, e.g. "foo.1.4" - * @return string the text from the specified cell - */ - // This regular expression matches "tableName.row.column" - // For example, "mytable.3.4" - pattern = /(.*)\.(\d+)\.(\d+)/; - - if(!pattern.test(tableCellAddress)) { - throw new SeleniumError("Invalid target format. Correct format is tableName.rowNum.columnNum"); - } - - pieces = tableCellAddress.match(pattern); - - tableName = pieces[1]; - row = pieces[2]; - col = pieces[3]; - - var table = this.browserbot.findElement(tableName); - if (row > table.rows.length) { - Assert.fail("Cannot access row " + row + " - table has " + table.rows.length + " rows"); - } - else if (col > table.rows[row].cells.length) { - Assert.fail("Cannot access column " + col + " - table row has " + table.rows[row].cells.length + " columns"); - } - else { - actualContent = getText(table.rows[row].cells[col]); - return actualContent.trim(); - } - return null; -}; - -Selenium.prototype.getSelectedLabels = function(selectLocator) { - /** Gets all option labels (visible text) for selected options in the specified select or multi-select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all selected option labels in the specified select drop-down - */ - return this.findSelectedOptionProperties(selectLocator, "text").join(","); -} - -Selenium.prototype.getSelectedLabel = function(selectLocator) { - /** Gets option label (visible text) for selected option in the specified select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string the selected option label in the specified select drop-down - */ - return this.findSelectedOptionProperty(selectLocator, "text"); -} - -Selenium.prototype.getSelectedValues = function(selectLocator) { - /** Gets all option values (value attributes) for selected options in the specified select or multi-select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all selected option values in the specified select drop-down - */ - return this.findSelectedOptionProperties(selectLocator, "value").join(","); -} - -Selenium.prototype.getSelectedValue = function(selectLocator) { - /** Gets option value (value attribute) for selected option in the specified select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string the selected option value in the specified select drop-down - */ - return this.findSelectedOptionProperty(selectLocator, "value"); -} - -Selenium.prototype.getSelectedIndexes = function(selectLocator) { - /** Gets all option indexes (option number, starting at 0) for selected options in the specified select or multi-select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all selected option indexes in the specified select drop-down - */ - return this.findSelectedOptionProperties(selectLocator, "index").join(","); -} - -Selenium.prototype.getSelectedIndex = function(selectLocator) { - /** Gets option index (option number, starting at 0) for selected option in the specified select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string the selected option index in the specified select drop-down - */ - return this.findSelectedOptionProperty(selectLocator, "index"); -} - -Selenium.prototype.getSelectedIds = function(selectLocator) { - /** Gets all option element IDs for selected options in the specified select or multi-select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all selected option IDs in the specified select drop-down - */ - return this.findSelectedOptionProperties(selectLocator, "id").join(","); -} - -Selenium.prototype.getSelectedId = function(selectLocator) { - /** Gets option element ID for selected option in the specified select element. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string the selected option ID in the specified select drop-down - */ - return this.findSelectedOptionProperty(selectLocator, "id"); -} - -Selenium.prototype.isSomethingSelected = function(selectLocator) { - /** Determines whether some option in a drop-down menu is selected. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return boolean true if some option has been selected, false otherwise - */ - var element = this.browserbot.findElement(selectLocator); - if (!("options" in element)) { - throw new SeleniumError("Specified element is not a Select (has no options)"); - } - - var selectedOptions = []; - - for (var i = 0; i < element.options.length; i++) { - if (element.options[i].selected) - { - return true; - } - } - return false; -} - -Selenium.prototype.findSelectedOptionProperties = function(locator, property) { - var element = this.browserbot.findElement(locator); - if (!("options" in element)) { - throw new SeleniumError("Specified element is not a Select (has no options)"); - } - - var selectedOptions = []; - - for (var i = 0; i < element.options.length; i++) { - if (element.options[i].selected) - { - var propVal = element.options[i][property]; - if (propVal.replace) { - propVal.replace(/,/g, "\\,"); - } - selectedOptions.push(propVal); - } - } - if (selectedOptions.length == 0) Assert.fail("No option selected"); - return selectedOptions; -} - -Selenium.prototype.findSelectedOptionProperty = function(locator, property) { - var selectedOptions = this.findSelectedOptionProperties(locator, property); - if (selectedOptions.length > 1) { - Assert.fail("More than one selected option!"); - } - return selectedOptions[0]; -} - -Selenium.prototype.getSelectOptions = function(selectLocator) { - /** Gets all option labels in the specified select drop-down. - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @return string[] an array of all option labels in the specified select drop-down - */ - var element = this.browserbot.findElement(selectLocator); - - var selectOptions = []; - - for (var i = 0; i < element.options.length; i++) { - var option = element.options[i].text.replace(/,/g, "\\,"); - selectOptions.push(option); - } - - return selectOptions.join(","); -}; - - -Selenium.prototype.getAttribute = function(attributeLocator) { - /** - * Gets the value of an element attribute. - * - * @param attributeLocator an element locator followed by an @ sign and then the name of the attribute, e.g. "foo@bar" - * @return string the value of the specified attribute - */ - var result = this.browserbot.findAttribute(attributeLocator); - if (result == null) { - throw new SeleniumError("Could not find element attribute: " + attributeLocator); - } - return result; -}; - -Selenium.prototype.isTextPresent = function(pattern) { - /** - * Verifies that the specified text pattern appears somewhere on the rendered page shown to the user. - * @param pattern a <a href="#patterns">pattern</a> to match with the text of the page - * @return boolean true if the pattern matches the text, false otherwise - */ - var allText = this.browserbot.bodyText(); - - var patternMatcher = new PatternMatcher(pattern); - if (patternMatcher.strategy == PatternMatcher.strategies.glob) { - if (pattern.indexOf("glob:")==0) { - pattern = pattern.substring("glob:".length); // strip off "glob:" - } - patternMatcher.matcher = new PatternMatcher.strategies.globContains(pattern); - } - else if (patternMatcher.strategy == PatternMatcher.strategies.exact) { - pattern = pattern.substring("exact:".length); // strip off "exact:" - return allText.indexOf(pattern) != -1; - } - return patternMatcher.matches(allText); -}; - -Selenium.prototype.isElementPresent = function(locator) { - /** - * Verifies that the specified element is somewhere on the page. - * @param locator an <a href="#locators">element locator</a> - * @return boolean true if the element is present, false otherwise - */ - try { - this.browserbot.findElement(locator); - } catch (e) { - return false; - } - return true; -}; - -Selenium.prototype.isVisible = function(locator) { - /** - * Determines if the specified element is visible. An - * element can be rendered invisible by setting the CSS "visibility" - * property to "hidden", or the "display" property to "none", either for the - * element itself or one if its ancestors. This method will fail if - * the element is not present. - * - * @param locator an <a href="#locators">element locator</a> - * @return boolean true if the specified element is visible, false otherwise - */ - var element; - element = this.browserbot.findElement(locator); - var visibility = this.findEffectiveStyleProperty(element, "visibility"); - var _isDisplayed = this._isDisplayed(element); - return (visibility != "hidden" && _isDisplayed); -}; - -Selenium.prototype.findEffectiveStyleProperty = function(element, property) { - var effectiveStyle = this.findEffectiveStyle(element); - var propertyValue = effectiveStyle[property]; - if (propertyValue == 'inherit' && element.parentNode.style) { - return this.findEffectiveStyleProperty(element.parentNode, property); - } - return propertyValue; -}; - -Selenium.prototype._isDisplayed = function(element) { - var display = this.findEffectiveStyleProperty(element, "display"); - if (display == "none") return false; - if (element.parentNode.style) { - return this._isDisplayed(element.parentNode); - } - return true; -}; - -Selenium.prototype.findEffectiveStyle = function(element) { - if (element.style == undefined) { - return undefined; // not a styled element - } - var window = this.browserbot.getCurrentWindow(); - if (window.getComputedStyle) { - // DOM-Level-2-CSS - return window.getComputedStyle(element, null); - } - if (element.currentStyle) { - // non-standard IE alternative - return element.currentStyle; - // TODO: this won't really work in a general sense, as - // currentStyle is not identical to getComputedStyle() - // ... but it's good enough for "visibility" - } - throw new SeleniumError("cannot determine effective stylesheet in this browser"); -}; - -Selenium.prototype.isEditable = function(locator) { - /** - * Determines whether the specified input element is editable, ie hasn't been disabled. - * This method will fail if the specified element isn't an input element. - * - * @param locator an <a href="#locators">element locator</a> - * @return boolean true if the input element is editable, false otherwise - */ - var element = this.browserbot.findElement(locator); - if (element.value == undefined) { - Assert.fail("Element " + locator + " is not an input."); - } - return !element.disabled; -}; - -Selenium.prototype.getAllButtons = function() { - /** Returns the IDs of all buttons on the page. - * - * <p>If a given button has no ID, it will appear as "" in this array.</p> - * - * @return string[] the IDs of all buttons on the page - */ - return this.browserbot.getAllButtons(); -}; - -Selenium.prototype.getAllLinks = function() { - /** Returns the IDs of all links on the page. - * - * <p>If a given link has no ID, it will appear as "" in this array.</p> - * - * @return string[] the IDs of all links on the page - */ - return this.browserbot.getAllLinks(); -}; - -Selenium.prototype.getAllFields = function() { - /** Returns the IDs of all input fields on the page. - * - * <p>If a given field has no ID, it will appear as "" in this array.</p> - * - * @return string[] the IDs of all field on the page - */ - return this.browserbot.getAllFields(); -}; - -Selenium.prototype.getAttributeFromAllWindows = function(attributeName) { - /** Returns every instance of some attribute from all known windows. - * - * @param attributeName name of an attribute on the windows - * @return string[] the set of values of this attribute from all known windows. - */ - var attributes = new Array(); - - var win = selenium.browserbot.topWindow; - - // DGF normally you should use []s instead of eval "win."+attributeName - // but in this case, attributeName may contain dots (e.g. document.title) - // in that case, we have no choice but to use eval... - attributes.push(eval("win."+attributeName)); - for (var windowName in this.browserbot.openedWindows) - { - try { - win = selenium.browserbot.openedWindows[windowName]; - attributes.push(eval("win."+attributeName)); - } catch (e) {} // DGF If we miss one... meh. It's probably closed or inaccessible anyway. - } - return attributes; -}; - -Selenium.prototype.findWindow = function(soughtAfterWindowPropertyValue) { - var targetPropertyName = "name"; - if (soughtAfterWindowPropertyValue.match("^title=")) { - targetPropertyName = "document.title"; - soughtAfterWindowPropertyValue = soughtAfterWindowPropertyValue.replace(/^title=/, ""); - } - else { - // matching "name": - // If we are not in proxy injection mode, then the top-level test window will be named myiframe. - // But as far as the interface goes, we are expected to match a blank string to this window, if - // we are searching with respect to the widow name. - // So make a special case so that this logic will work: - if (PatternMatcher.matches(soughtAfterWindowPropertyValue, "")) { - return this.browserbot.getCurrentWindow(); - } - } - - // DGF normally you should use []s instead of eval "win."+attributeName - // but in this case, attributeName may contain dots (e.g. document.title) - // in that case, we have no choice but to use eval... - if (PatternMatcher.matches(soughtAfterWindowPropertyValue, eval("this.browserbot.topWindow." + targetPropertyName))) { - return this.browserbot.topWindow; - } - for (windowName in selenium.browserbot.openedWindows) { - var openedWindow = selenium.browserbot.openedWindows[windowName]; - if (PatternMatcher.matches(soughtAfterWindowPropertyValue, eval("openedWindow." + targetPropertyName))) { - return openedWindow; - } - } - throw new SeleniumError("could not find window with property " + targetPropertyName + " matching " + soughtAfterWindowPropertyValue); -}; - -Selenium.prototype.doDragdrop = function(locator, movementsString) { -/** deprecated - use dragAndDrop instead - * - * @param locator an element locator - * @param movementsString offset in pixels from the current location to which the element should be moved, e.g., "+70,-300" - */ - this.doDragAndDrop(locator, movementsString); -}; - -Selenium.prototype.doSetMouseSpeed = function(pixels) { - /** Configure the number of pixels between "mousemove" events during dragAndDrop commands (default=10). - * <p>Setting this value to 0 means that we'll send a "mousemove" event to every single pixel - * in between the start location and the end location; that can be very slow, and may - * cause some browsers to force the JavaScript to timeout.</p> - * - * <p>If the mouse speed is greater than the distance between the two dragged objects, we'll - * just send one "mousemove" at the start location and then one final one at the end location.</p> - * @param pixels the number of pixels between "mousemove" events - */ - this.mouseSpeed = pixels; -} - -Selenium.prototype.getMouseSpeed = function() { - /** Returns the number of pixels between "mousemove" events during dragAndDrop commands (default=10). - * - * @return number the number of pixels between "mousemove" events during dragAndDrop commands (default=10) - */ - this.mouseSpeed = pixels; -} - - -Selenium.prototype.doDragAndDrop = function(locator, movementsString) { - /** Drags an element a certain distance and then drops it - * @param locator an element locator - * @param movementsString offset in pixels from the current location to which the element should be moved, e.g., "+70,-300" - */ - var element = this.browserbot.findElement(locator); - var clientStartXY = getClientXY(element) - var clientStartX = clientStartXY[0]; - var clientStartY = clientStartXY[1]; - - var movements = movementsString.split(/,/); - var movementX = Number(movements[0]); - var movementY = Number(movements[1]); - - var clientFinishX = ((clientStartX + movementX) < 0) ? 0 : (clientStartX + movementX); - var clientFinishY = ((clientStartY + movementY) < 0) ? 0 : (clientStartY + movementY); - - var mouseSpeed = this.mouseSpeed; - var move = function(current, dest) { - if (current == dest) return current; - if (Math.abs(current - dest) < mouseSpeed) return dest; - return (current < dest) ? current + mouseSpeed : current - mouseSpeed; - } - - this.browserbot.triggerMouseEvent(element, 'mousedown', true, clientStartX, clientStartY); - this.browserbot.triggerMouseEvent(element, 'mousemove', true, clientStartX, clientStartY); - var clientX = clientStartX; - var clientY = clientStartY; - - while ((clientX != clientFinishX) || (clientY != clientFinishY)) { - clientX = move(clientX, clientFinishX); - clientY = move(clientY, clientFinishY); - this.browserbot.triggerMouseEvent(element, 'mousemove', true, clientX, clientY); - } - - this.browserbot.triggerMouseEvent(element, 'mousemove', true, clientFinishX, clientFinishY); - this.browserbot.triggerMouseEvent(element, 'mouseup', true, clientFinishX, clientFinishY); -}; - -Selenium.prototype.doDragAndDropToObject = function(locatorOfObjectToBeDragged, locatorOfDragDestinationObject) { -/** Drags an element and drops it on another element - * - * @param locatorOfObjectToBeDragged an element to be dragged - * @param locatorOfDragDestinationObject an element whose location (i.e., whose center-most pixel) will be the point where locatorOfObjectToBeDragged is dropped - */ - var startX = this.getElementPositionLeft(locatorOfObjectToBeDragged); - var startY = this.getElementPositionTop(locatorOfObjectToBeDragged); - - var destinationLeftX = this.getElementPositionLeft(locatorOfDragDestinationObject); - var destinationTopY = this.getElementPositionTop(locatorOfDragDestinationObject); - var destinationWidth = this.getElementWidth(locatorOfDragDestinationObject); - var destinationHeight = this.getElementHeight(locatorOfDragDestinationObject); - - var endX = Math.round(destinationLeftX + (destinationWidth / 2)); - var endY = Math.round(destinationTopY + (destinationHeight / 2)); - - var deltaX = endX - startX; - var deltaY = endY - startY; - - var movementsString = "" + deltaX + "," + deltaY; - - this.doDragAndDrop(locatorOfObjectToBeDragged, movementsString); -}; - -Selenium.prototype.doWindowFocus = function(windowName) { -/** Gives focus to a window - * - * @param windowName name of the window to be given focus - */ - this.findWindow(windowName).focus(); -}; - - -Selenium.prototype.doWindowMaximize = function(windowName) { -/** Resize window to take up the entire screen - * - * @param windowName name of the window to be enlarged - */ - var window = this.findWindow(windowName); - if (window!=null && window.screen) { - window.moveTo(0,0); - window.outerHeight = screen.availHeight; - window.outerWidth = screen.availWidth; - } -}; - -Selenium.prototype.getAllWindowIds = function() { - /** Returns the IDs of all windows that the browser knows about. - * - * @return string[] the IDs of all windows that the browser knows about. - */ - return this.getAttributeFromAllWindows("id"); -}; - -Selenium.prototype.getAllWindowNames = function() { - /** Returns the names of all windows that the browser knows about. - * - * @return string[] the names of all windows that the browser knows about. - */ - return this.getAttributeFromAllWindows("name"); -}; - -Selenium.prototype.getAllWindowTitles = function() { - /** Returns the titles of all windows that the browser knows about. - * - * @return string[] the titles of all windows that the browser knows about. - */ - return this.getAttributeFromAllWindows("document.title"); -}; - -Selenium.prototype.getHtmlSource = function() { - /** Returns the entire HTML source between the opening and - * closing "html" tags. - * - * @return string the entire HTML source - */ - return this.browserbot.getDocument().getElementsByTagName("html")[0].innerHTML; -}; - -Selenium.prototype.doSetCursorPosition = function(locator, position) { - /** - * Moves the text cursor to the specified position in the given input element or textarea. - * This method will fail if the specified element isn't an input element or textarea. - * - * @param locator an <a href="#locators">element locator</a> pointing to an input element or textarea - * @param position the numerical position of the cursor in the field; position should be 0 to move the position to the beginning of the field. You can also set the cursor to -1 to move it to the end of the field. - */ - var element = this.browserbot.findElement(locator); - if (element.value == undefined) { - Assert.fail("Element " + locator + " is not an input."); - } - if (position == -1) { - position = element.value.length; - } - - if( element.setSelectionRange && !browserVersion.isOpera) { - element.focus(); - element.setSelectionRange(/*start*/position,/*end*/position); - } - else if( element.createTextRange ) { - triggerEvent(element, 'focus', false); - var range = element.createTextRange(); - range.collapse(true); - range.moveEnd('character',position); - range.moveStart('character',position); - range.select(); - } -} - -Selenium.prototype.getElementIndex = function(locator) { - /** - * Get the relative index of an element to its parent (starting from 0). The comment node and empty text node - * will be ignored. - * - * @param locator an <a href="#locators">element locator</a> pointing to an element - * @return number of relative index of the element to its parent (starting from 0) - */ - var element = this.browserbot.findElement(locator); - var previousSibling; - var index = 0; - while ((previousSibling = element.previousSibling) != null) { - if (!this._isCommentOrEmptyTextNode(previousSibling)) { - index++; - } - element = previousSibling; - } - return index; -} - -Selenium.prototype.isOrdered = function(locator1, locator2) { - /** - * Check if these two elements have same parent and are ordered. Two same elements will - * not be considered ordered. - * - * @param locator1 an <a href="#locators">element locator</a> pointing to the first element - * @param locator2 an <a href="#locators">element locator</a> pointing to the second element - * @return boolean true if two elements are ordered and have same parent, false otherwise - */ - var element1 = this.browserbot.findElement(locator1); - var element2 = this.browserbot.findElement(locator2); - if (element1 === element2) return false; - - var previousSibling; - while ((previousSibling = element2.previousSibling) != null) { - if (previousSibling === element1) { - return true; - } - element2 = previousSibling; - } - return false; -} - -Selenium.prototype._isCommentOrEmptyTextNode = function(node) { - return node.nodeType == 8 || ((node.nodeType == 3) && !(/[^\t\n\r ]/.test(node.data))); -} - -Selenium.prototype.getElementPositionLeft = function(locator) { - /** - * Retrieves the horizontal position of an element - * - * @param locator an <a href="#locators">element locator</a> pointing to an element OR an element itself - * @return number of pixels from the edge of the frame. - */ - var element; - if ("string"==typeof locator) { - element = this.browserbot.findElement(locator); - } - else { - element = locator; - } - var x = element.offsetLeft; - var elementParent = element.offsetParent; - - while (elementParent != null) - { - if(document.all) - { - if( (elementParent.tagName != "TABLE") && (elementParent.tagName != "BODY") ) - { - x += elementParent.clientLeft; - } - } - else // Netscape/DOM - { - if(elementParent.tagName == "TABLE") - { - var parentBorder = parseInt(elementParent.border); - if(isNaN(parentBorder)) - { - var parentFrame = elementParent.getAttribute('frame'); - if(parentFrame != null) - { - x += 1; - } - } - else if(parentBorder > 0) - { - x += parentBorder; - } - } - } - x += elementParent.offsetLeft; - elementParent = elementParent.offsetParent; - } - return x; -}; - -Selenium.prototype.getElementPositionTop = function(locator) { - /** - * Retrieves the vertical position of an element - * - * @param locator an <a href="#locators">element locator</a> pointing to an element OR an element itself - * @return number of pixels from the edge of the frame. - */ - var element; - if ("string"==typeof locator) { - element = this.browserbot.findElement(locator); - } - else { - element = locator; - } - - var y = 0; - - while (element != null) - { - if(document.all) - { - if( (element.tagName != "TABLE") && (element.tagName != "BODY") ) - { - y += element.clientTop; - } - } - else // Netscape/DOM - { - if(element.tagName == "TABLE") - { - var parentBorder = parseInt(element.border); - if(isNaN(parentBorder)) - { - var parentFrame = element.getAttribute('frame'); - if(parentFrame != null) - { - y += 1; - } - } - else if(parentBorder > 0) - { - y += parentBorder; - } - } - } - y += element.offsetTop; - - // Netscape can get confused in some cases, such that the height of the parent is smaller - // than that of the element (which it shouldn't really be). If this is the case, we need to - // exclude this element, since it will result in too large a 'top' return value. - if (element.offsetParent && element.offsetParent.offsetHeight && element.offsetParent.offsetHeight < element.offsetHeight) - { - // skip the parent that's too small - element = element.offsetParent.offsetParent; - } - else - { - // Next up... - element = element.offsetParent; - } - } - return y; -}; - -Selenium.prototype.getElementWidth = function(locator) { - /** - * Retrieves the width of an element - * - * @param locator an <a href="#locators">element locator</a> pointing to an element - * @return number width of an element in pixels - */ - var element = this.browserbot.findElement(locator); - return element.offsetWidth; -}; - -Selenium.prototype.getElementHeight = function(locator) { - /** - * Retrieves the height of an element - * - * @param locator an <a href="#locators">element locator</a> pointing to an element - * @return number height of an element in pixels - */ - var element = this.browserbot.findElement(locator); - return element.offsetHeight; -}; - -Selenium.prototype.getCursorPosition = function(locator) { - /** - * Retrieves the text cursor position in the given input element or textarea; beware, this may not work perfectly on all browsers. - * - * <p>Specifically, if the cursor/selection has been cleared by JavaScript, this command will tend to - * return the position of the last location of the cursor, even though the cursor is now gone from the page. This is filed as <a href="http://jira.openqa.org/browse/SEL-243">SEL-243</a>.</p> - * This method will fail if the specified element isn't an input element or textarea, or there is no cursor in the element. - * - * @param locator an <a href="#locators">element locator</a> pointing to an input element or textarea - * @return number the numerical position of the cursor in the field - */ - var element = this.browserbot.findElement(locator); - var doc = this.browserbot.getDocument(); - var win = this.browserbot.getCurrentWindow(); - if( doc.selection && !browserVersion.isOpera){ - try { - var selectRange = doc.selection.createRange().duplicate(); - var elementRange = element.createTextRange(); - selectRange.move("character",0); - elementRange.move("character",0); - var inRange1 = selectRange.inRange(elementRange); - var inRange2 = elementRange.inRange(selectRange); - elementRange.setEndPoint("EndToEnd", selectRange); - } catch (e) { - Assert.fail("There is no cursor on this page!"); - } - var answer = String(elementRange.text).replace(/\r/g,"").length; - return answer; - } else { - if (typeof(element.selectionStart) != "undefined") { - if (win.getSelection && typeof(win.getSelection().rangeCount) != undefined && win.getSelection().rangeCount == 0) { - Assert.fail("There is no cursor on this page!"); - } - return element.selectionStart; - } - } - throw new Error("Couldn't detect cursor position on this browser!"); -} - - -Selenium.prototype.doSetContext = function(context, logLevelThreshold) { - /** - * Writes a message to the status bar and adds a note to the browser-side - * log. - * - * <p>If logLevelThreshold is specified, set the threshold for logging - * to that level (debug, info, warn, error).</p> - * - * <p>(Note that the browser-side logs will <i>not</i> be sent back to the - * server, and are invisible to the Client Driver.)</p> - * - * @param context - * the message to be sent to the browser - * @param logLevelThreshold one of "debug", "info", "warn", "error", sets the threshold for browser-side logging - */ - if (logLevelThreshold==null || logLevelThreshold=="") { - return this.browserbot.setContext(context); - } - return this.browserbot.setContext(context, logLevelThreshold); -}; - -Selenium.prototype.getExpression = function(expression) { - /** - * Returns the specified expression. - * - * <p>This is useful because of JavaScript preprocessing. - * It is used to generate commands like assertExpression and waitForExpression.</p> - * - * @param expression the value to return - * @return string the value passed in - */ - return expression; -} - -Selenium.prototype.doWaitForCondition = function(script, timeout) { - /** - * Runs the specified JavaScript snippet repeatedly until it evaluates to "true". - * The snippet may have multiple lines, but only the result of the last line - * will be considered. - * - * <p>Note that, by default, the snippet will be run in the runner's test window, not in the window - * of your application. To get the window of your application, you can use - * the JavaScript snippet <code>selenium.browserbot.getCurrentWindow()</code>, and then - * run your JavaScript in there</p> - * @param script the JavaScript snippet to run - * @param timeout a timeout in milliseconds, after which this command will return with an error - */ - return Selenium.decorateFunctionWithTimeout(function () { - return eval(script); - }, timeout); -}; - -Selenium.prototype.doWaitForCondition.dontCheckAlertsAndConfirms = true; - -Selenium.prototype.doSetTimeout = function(timeout) { - /** - * Specifies the amount of time that Selenium will wait for actions to complete. - * - * <p>Actions that require waiting include "open" and the "waitFor*" actions.</p> - * The default timeout is 30 seconds. - * @param timeout a timeout in milliseconds, after which the action will return with an error - */ - if (!timeout) { - timeout = Selenium.DEFAULT_TIMEOUT; - } - this.defaultTimeout = timeout; -} - -Selenium.prototype.doWaitForPageToLoad = function(timeout) { - /** - * Waits for a new page to load. - * - * <p>You can use this command instead of the "AndWait" suffixes, "clickAndWait", "selectAndWait", "typeAndWait" etc. - * (which are only available in the JS API).</p> - * - * <p>Selenium constantly keeps track of new pages loading, and sets a "newPageLoaded" - * flag when it first notices a page load. Running any other Selenium command after - * turns the flag to false. Hence, if you want to wait for a page to load, you must - * wait immediately after a Selenium command that caused a page-load.</p> - * @param timeout a timeout in milliseconds, after which this command will return with an error - */ - // in pi-mode, the test and the harness share the window; thus if we are executing this code, then we have loaded - if (window["proxyInjectionMode"] == null || !window["proxyInjectionMode"]) { - return this.makePageLoadCondition(timeout); - } -}; - -Selenium.prototype._isNewPageLoaded = function() { - return this.browserbot.isNewPageLoaded(); -}; - -Selenium.prototype.doWaitForPageToLoad.dontCheckAlertsAndConfirms = true; - -/** - * Evaluate a parameter, performing JavaScript evaluation and variable substitution. - * If the string matches the pattern "javascript{ ... }", evaluate the string between the braces. - */ -Selenium.prototype.preprocessParameter = function(value) { - var match = value.match(/^javascript\{((.|\r?\n)+)\}$/); - if (match && match[1]) { - return eval(match[1]).toString(); - } - return this.replaceVariables(value); -}; - -/* - * Search through str and replace all variable references ${varName} with their - * value in storedVars. - */ -Selenium.prototype.replaceVariables = function(str) { - var stringResult = str; - - // Find all of the matching variable references - var match = stringResult.match(/\$\{\w+\}/g); - if (!match) { - return stringResult; - } - - // For each match, lookup the variable value, and replace if found - for (var i = 0; match && i < match.length; i++) { - var variable = match[i]; // The replacement variable, with ${} - var name = variable.substring(2, variable.length - 1); // The replacement variable without ${} - var replacement = storedVars[name]; - if (replacement != undefined) { - stringResult = stringResult.replace(variable, replacement); - } - } - return stringResult; -}; - -Selenium.prototype.getCookie = function() { - /** - * Return all cookies of the current page under test. - * - * @return string all cookies of the current page under test - */ - var doc = this.browserbot.getDocument(); - return doc.cookie; -}; - -Selenium.prototype.doCreateCookie = function(nameValuePair, optionsString) { - /** - * Create a new cookie whose path and domain are same with those of current page - * under test, unless you specified a path for this cookie explicitly. - * - * @param nameValuePair name and value of the cookie in a format "name=value" - * @param optionsString options for the cookie. Currently supported options include 'path' and 'max_age'. - * the optionsString's format is "path=/path/, max_age=60". The order of options are irrelevant, the unit - * of the value of 'max_age' is second. - */ - var results = /[^\s=\[\]\(\),"\/\?@:;]+=[^\s=\[\]\(\),"\/\?@:;]*/.test(nameValuePair); - if (!results) { - throw new SeleniumError("Invalid parameter."); - } - var cookie = nameValuePair.trim(); - results = /max_age=(\d+)/.exec(optionsString); - if (results) { - var expireDateInMilliseconds = (new Date()).getTime() + results[1] * 1000; - cookie += "; expires=" + new Date(expireDateInMilliseconds).toGMTString(); - } - results = /path=([^\s,]+)[,]?/.exec(optionsString); - if (results) { - var path = results[1]; - if (browserVersion.khtml) { - // Safari and conquerer don't like paths with / at the end - if ("/" != path) { - path = path.replace(/\/$/, ""); - } - } - cookie += "; path=" + path; - } - LOG.debug("Setting cookie to: " + cookie); - this.browserbot.getDocument().cookie = cookie; -} - -Selenium.prototype.doDeleteCookie = function(name,path) { - /** - * Delete a named cookie with specified path. - * - * @param name the name of the cookie to be deleted - * @param path the path property of the cookie to be deleted - */ - // set the expire time of the cookie to be deleted to one minute before now. - path = path.trim(); - if (browserVersion.khtml) { - // Safari and conquerer don't like paths with / at the end - if ("/" != path) { - path = path.replace(/\/$/, ""); - } - } - var expireDateInMilliseconds = (new Date()).getTime() + (-1 * 1000); - var cookie = name.trim() + "=deleted; path=" + path + "; expires=" + new Date(expireDateInMilliseconds).toGMTString(); - LOG.debug("Setting cookie to: " + cookie); - this.browserbot.getDocument().cookie = cookie; -} - - -/** - * Factory for creating "Option Locators". - * An OptionLocator is an object for dealing with Select options (e.g. for - * finding a specified option, or asserting that the selected option of - * Select element matches some condition. - * The type of locator returned by the factory depends on the locator string: - * label=<exp> (OptionLocatorByLabel) - * value=<exp> (OptionLocatorByValue) - * index=<exp> (OptionLocatorByIndex) - * id=<exp> (OptionLocatorById) - * <exp> (default is OptionLocatorByLabel). - */ -function OptionLocatorFactory() { -} - -OptionLocatorFactory.prototype.fromLocatorString = function(locatorString) { - var locatorType = 'label'; - var locatorValue = locatorString; - // If there is a locator prefix, use the specified strategy - var result = locatorString.match(/^([a-zA-Z]+)=(.*)/); - if (result) { - locatorType = result[1]; - locatorValue = result[2]; - } - if (this.optionLocators == undefined) { - this.registerOptionLocators(); - } - if (this.optionLocators[locatorType]) { - return new this.optionLocators[locatorType](locatorValue); - } - throw new SeleniumError("Unkown option locator type: " + locatorType); -}; - -/** - * To allow for easy extension, all of the option locators are found by - * searching for all methods of OptionLocatorFactory.prototype that start - * with "OptionLocatorBy". - * TODO: Consider using the term "Option Specifier" instead of "Option Locator". - */ -OptionLocatorFactory.prototype.registerOptionLocators = function() { - this.optionLocators={}; - for (var functionName in this) { - var result = /OptionLocatorBy([A-Z].+)$/.exec(functionName); - if (result != null) { - var locatorName = result[1].lcfirst(); - this.optionLocators[locatorName] = this[functionName]; - } - } -}; - -/** - * OptionLocator for options identified by their labels. - */ -OptionLocatorFactory.prototype.OptionLocatorByLabel = function(label) { - this.label = label; - this.labelMatcher = new PatternMatcher(this.label); - this.findOption = function(element) { - for (var i = 0; i < element.options.length; i++) { - if (this.labelMatcher.matches(element.options[i].text)) { - return element.options[i]; - } - } - throw new SeleniumError("Option with label '" + this.label + "' not found"); - }; - - this.assertSelected = function(element) { - var selectedLabel = element.options[element.selectedIndex].text; - Assert.matches(this.label, selectedLabel) - }; -}; - -/** - * OptionLocator for options identified by their values. - */ -OptionLocatorFactory.prototype.OptionLocatorByValue = function(value) { - this.value = value; - this.valueMatcher = new PatternMatcher(this.value); - this.findOption = function(element) { - for (var i = 0; i < element.options.length; i++) { - if (this.valueMatcher.matches(element.options[i].value)) { - return element.options[i]; - } - } - throw new SeleniumError("Option with value '" + this.value + "' not found"); - }; - - this.assertSelected = function(element) { - var selectedValue = element.options[element.selectedIndex].value; - Assert.matches(this.value, selectedValue) - }; -}; - -/** - * OptionLocator for options identified by their index. - */ -OptionLocatorFactory.prototype.OptionLocatorByIndex = function(index) { - this.index = Number(index); - if (isNaN(this.index) || this.index < 0) { - throw new SeleniumError("Illegal Index: " + index); - } - - this.findOption = function(element) { - if (element.options.length <= this.index) { - throw new SeleniumError("Index out of range. Only " + element.options.length + " options available"); - } - return element.options[this.index]; - }; - - this.assertSelected = function(element) { - Assert.equals(this.index, element.selectedIndex); - }; -}; - -/** - * OptionLocator for options identified by their id. - */ -OptionLocatorFactory.prototype.OptionLocatorById = function(id) { - this.id = id; - this.idMatcher = new PatternMatcher(this.id); - this.findOption = function(element) { - for (var i = 0; i < element.options.length; i++) { - if (this.idMatcher.matches(element.options[i].id)) { - return element.options[i]; - } - } - throw new SeleniumError("Option with id '" + this.id + "' not found"); - }; - - this.assertSelected = function(element) { - var selectedId = element.options[element.selectedIndex].id; - Assert.matches(this.id, selectedId) - }; -}; diff --git a/tests/test_tools/selenium/core/scripts/selenium-browserbot.js b/tests/test_tools/selenium/core/scripts/selenium-browserbot.js deleted file mode 100644 index 633289e2..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-browserbot.js +++ /dev/null @@ -1,1946 +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 provides the Javascript API to drive the test application contained within -* a Browser Window. -* TODO: -* Add support for more events (keyboard and mouse) -* Allow to switch "user-entry" mode from mouse-based to keyboard-based, firing different -* events in different modes. -*/ - -// The window to which the commands will be sent. For example, to click on a -// popup window, first select that window, and then do a normal click command. -var BrowserBot = function(topLevelApplicationWindow) { - this.topWindow = topLevelApplicationWindow; - this.topFrame = this.topWindow; - this.baseUrl=window.location.href; - - // the buttonWindow is the Selenium window - // it contains the Run/Pause buttons... this should *not* be the AUT window - this.buttonWindow = window; - this.currentWindow = this.topWindow; - this.currentWindowName = null; - - // We need to know this in advance, in case the frame closes unexpectedly - this.isSubFrameSelected = false; - - this.altKeyDown = false; - this.controlKeyDown = false; - this.shiftKeyDown = false; - this.metaKeyDown = false; - - this.modalDialogTest = null; - this.recordedAlerts = new Array(); - this.recordedConfirmations = new Array(); - this.recordedPrompts = new Array(); - this.openedWindows = {}; - this.nextConfirmResult = true; - this.nextPromptResult = ''; - this.newPageLoaded = false; - this.pageLoadError = null; - - this.shouldHighlightLocatedElement = false; - - this.uniqueId = new Date().getTime(); - this.pollingForLoad = new Object(); - this.permDeniedCount = new Object(); - this.windowPollers = new Array(); - // DGF for backwards compatibility - this.browserbot = this; - - var self = this; - - objectExtend(this, PageBot.prototype); - this._registerAllLocatorFunctions(); - - this.recordPageLoad = function(elementOrWindow) { - LOG.debug("Page load detected"); - try { - if (elementOrWindow.location && elementOrWindow.location.href) { - LOG.debug("Page load location=" + elementOrWindow.location.href); - } else if (elementOrWindow.contentWindow && elementOrWindow.contentWindow.location && elementOrWindow.contentWindow.location.href) { - LOG.debug("Page load location=" + elementOrWindow.contentWindow.location.href); - } else { - LOG.debug("Page load location unknown, current window location=" + this.getCurrentWindow(true).location); - } - } catch (e) { - LOG.error("Caught an exception attempting to log location; this should get noticed soon!"); - LOG.exception(e); - self.pageLoadError = e; - return; - } - self.newPageLoaded = true; - }; - - this.isNewPageLoaded = function() { - if (this.pageLoadError) { - LOG.error("isNewPageLoaded found an old pageLoadError"); - var e = this.pageLoadError; - this.pageLoadError = null; - throw e; - } - return self.newPageLoaded; - }; - -}; - -// DGF PageBot exists for backwards compatibility with old user-extensions -var PageBot = function(){}; - -BrowserBot.createForWindow = function(window, proxyInjectionMode) { - var browserbot; - LOG.debug('createForWindow'); - LOG.debug("browserName: " + browserVersion.name); - LOG.debug("userAgent: " + navigator.userAgent); - if (browserVersion.isIE) { - browserbot = new IEBrowserBot(window); - } - else if (browserVersion.isKonqueror) { - browserbot = new KonquerorBrowserBot(window); - } - else if (browserVersion.isOpera) { - browserbot = new OperaBrowserBot(window); - } - else if (browserVersion.isSafari) { - browserbot = new SafariBrowserBot(window); - } - else { - // Use mozilla by default - browserbot = new MozillaBrowserBot(window); - } - // getCurrentWindow has the side effect of modifying it to handle page loads etc - browserbot.proxyInjectionMode = proxyInjectionMode; - browserbot.getCurrentWindow(); // for modifyWindow side effect. This is not a transparent style - return browserbot; -}; - -// todo: rename? This doesn't actually "do" anything. -BrowserBot.prototype.doModalDialogTest = function(test) { - this.modalDialogTest = test; -}; - -BrowserBot.prototype.cancelNextConfirmation = function() { - this.nextConfirmResult = false; -}; - -BrowserBot.prototype.setNextPromptResult = function(result) { - this.nextPromptResult = result; -}; - -BrowserBot.prototype.hasAlerts = function() { - return (this.recordedAlerts.length > 0); -}; - -BrowserBot.prototype.relayBotToRC = function() { -}; -// override in injection.html - -BrowserBot.prototype.resetPopups = function() { - this.recordedAlerts = []; - this.recordedConfirmations = []; - this.recordedPrompts = []; -} - -BrowserBot.prototype.getNextAlert = function() { - var t = this.recordedAlerts.shift(); - this.relayBotToRC("browserbot.recordedAlerts"); - return t; -}; - -BrowserBot.prototype.hasConfirmations = function() { - return (this.recordedConfirmations.length > 0); -}; - -BrowserBot.prototype.getNextConfirmation = function() { - var t = this.recordedConfirmations.shift(); - this.relayBotToRC("browserbot.recordedConfirmations"); - return t; -}; - -BrowserBot.prototype.hasPrompts = function() { - return (this.recordedPrompts.length > 0); -}; - -BrowserBot.prototype.getNextPrompt = function() { - var t = this.recordedPrompts.shift(); - this.relayBotToRC("browserbot.recordedPrompts"); - return t; -}; - -/* Fire a mouse event in a browser-compatible manner */ - -BrowserBot.prototype.triggerMouseEvent = function(element, eventType, canBubble, clientX, clientY) { - clientX = clientX ? clientX : 0; - clientY = clientY ? clientY : 0; - - LOG.warn("triggerMouseEvent assumes setting screenX and screenY to 0 is ok"); - var screenX = 0; - var screenY = 0; - - canBubble = (typeof(canBubble) == undefined) ? true : canBubble; - if (element.fireEvent) { - LOG.info("element has fireEvent"); - var evt = createEventObject(element, this.controlKeyDown, this.altKeyDown, this.shiftKeyDown, this.metaKeyDown); - evt.detail = 0; - evt.button = 1; - evt.relatedTarget = null; - if (!screenX && !screenY && !clientX && !clientY && !this.controlKeyDown && !this.altKeyDown && !this.shiftKeyDown && !this.metaKeyDown) { - element.fireEvent('on' + eventType); - } - else { - evt.screenX = screenX; - evt.screenY = screenY; - evt.clientX = clientX; - evt.clientY = clientY; - - // when we go this route, window.event is never set to contain the event we have just created. - // ideally we could just slide it in as follows in the try-block below, but this normally - // doesn't work. This is why I try to avoid this code path, which is only required if we need to - // set attributes on the event (e.g., clientX). - try { - window.event = evt; - } - catch(e) { - // getting an "Object does not support this action or property" error. Save the event away - // for future reference. - // TODO: is there a way to update window.event? - - // work around for http://jira.openqa.org/browse/SEL-280 -- make the event available somewhere: - selenium.browserbot.getCurrentWindow().selenium_event = evt; - } - element.fireEvent('on' + eventType, evt); - } - } - else { - LOG.info("element doesn't have fireEvent"); - var evt = document.createEvent('MouseEvents'); - if (evt.initMouseEvent) - { - LOG.info("element has initMouseEvent"); - //Safari - evt.initMouseEvent(eventType, canBubble, true, document.defaultView, 1, screenX, screenY, clientX, clientY, - this.controlKeyDown, this.altKeyDown, this.shiftKeyDown, this.metaKeyDown, 0, null); - } - else { - LOG.warn("element doesn't have initMouseEvent; firing an event which should -- but doesn't -- have other mouse-event related attributes here, as well as controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown"); - evt.initEvent(eventType, canBubble, true); - - evt.shiftKey = this.shiftKeyDown; - evt.metaKey = this.metaKeyDown; - evt.altKey = this.altKeyDown; - evt.ctrlKey = this.controlKeyDown; - - } - element.dispatchEvent(evt); - } -} - -BrowserBot.prototype._windowClosed = function(win) { - var c = win.closed; - if (c == null) return true; - return c; -}; - -BrowserBot.prototype._modifyWindow = function(win) { - // In proxyInjectionMode, have to suppress LOG calls in _modifyWindow to avoid an infinite loop - if (this._windowClosed(win)) { - if (!this.proxyInjectionMode) { - LOG.error("modifyWindow: Window was closed!"); - } - return null; - } - if (!this.proxyInjectionMode) { - LOG.debug('modifyWindow ' + this.uniqueId + ":" + win[this.uniqueId]); - } - if (!win[this.uniqueId]) { - win[this.uniqueId] = true; - this.modifyWindowToRecordPopUpDialogs(win, this); - } - // In proxyInjection mode, we have our own mechanism for detecting page loads - if (!this.proxyInjectionMode) { - this.modifySeparateTestWindowToDetectPageLoads(win); - } - if (win.frames && win.frames.length && win.frames.length > 0) { - for (var i = 0; i < win.frames.length; i++) { - try { - this._modifyWindow(win.frames[i]); - } catch (e) {} // we're just trying to be opportunistic; don't worry if this doesn't work out - } - } - return win; -}; - -BrowserBot.prototype.selectWindow = function(target) { - if (target && target != "null") { - this._selectWindowByName(target); - } else { - this._selectTopWindow(); - } -}; - -BrowserBot.prototype._selectTopWindow = function() { - this.currentWindowName = null; - this.currentWindow = this.topWindow; - this.topFrame = this.topWindow; - this.isSubFrameSelected = false; -} - -BrowserBot.prototype._selectWindowByName = function(target) { - this.currentWindow = this.getWindowByName(target, false); - this.topFrame = this.currentWindow; - this.currentWindowName = target; - this.isSubFrameSelected = false; -} - -BrowserBot.prototype.selectFrame = function(target) { - if (target == "relative=up") { - this.currentWindow = this.getCurrentWindow().parent; - this.isSubFrameSelected = (this._getFrameElement(this.currentWindow) != null); - } else if (target == "relative=top") { - this.currentWindow = this.topFrame; - this.isSubFrameSelected = false; - } else { - var frame = this.findElement(target); - if (frame == null) { - throw new SeleniumError("Not found: " + target); - } - // now, did they give us a frame or a frame ELEMENT? - var match = false; - if (frame.contentWindow) { - // this must be a frame element - if (browserVersion.isHTA) { - // stupid HTA bug; can't get in the front door - target = frame.contentWindow.name; - } else { - this.currentWindow = frame.contentWindow; - this.isSubFrameSelected = true; - match = true; - } - } else if (frame.document && frame.location) { - // must be an actual window frame - this.currentWindow = frame; - this.isSubFrameSelected = true; - match = true; - } - - if (!match) { - // neither, let's loop through the frame names - var win = this.getCurrentWindow(); - - if (win && win.frames && win.frames.length) { - for (var i = 0; i < win.frames.length; i++) { - if (win.frames[i].name == target) { - this.currentWindow = win.frames[i]; - this.isSubFrameSelected = true; - match = true; - break; - } - } - } - if (!match) { - throw new SeleniumError("Not a frame: " + target); - } - } - } - // modifies the window - this.getCurrentWindow(); -}; - -BrowserBot.prototype.openLocation = function(target) { - // We're moving to a new page - clear the current one - var win = this.getCurrentWindow(); - LOG.debug("openLocation newPageLoaded = false"); - this.newPageLoaded = false; - - this.setOpenLocation(win, target); -}; - -BrowserBot.prototype.openWindow = function(url, windowID) { - if (url != "") { - url = absolutify(url, this.baseUrl); - } - if (browserVersion.isHTA) { - // in HTA mode, calling .open on the window interprets the url relative to that window - // we need to absolute-ize the URL to make it consistent - var child = this.getCurrentWindow().open(url, windowID); - selenium.browserbot.openedWindows[windowID] = child; - } else { - this.getCurrentWindow().open(url, windowID); - } -}; - -BrowserBot.prototype.setIFrameLocation = function(iframe, location) { - iframe.src = location; -}; - -BrowserBot.prototype.setOpenLocation = function(win, loc) { - loc = absolutify(loc, this.baseUrl); - if (browserVersion.isHTA) { - var oldHref = win.location.href; - win.location.href = loc; - var marker = null; - try { - marker = this.isPollingForLoad(win); - if (marker && win.location[marker]) { - win.location[marker] = false; - } - } catch (e) {} // DGF don't know why, but this often fails - } else { - win.location.href = loc; - } -}; - -BrowserBot.prototype.getCurrentPage = function() { - return this; -}; - -BrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { - var self = this; - - windowToModify.alert = function(alert) { - browserBot.recordedAlerts.push(alert); - self.relayBotToRC("browserbot.recordedAlerts"); - }; - - windowToModify.confirm = function(message) { - browserBot.recordedConfirmations.push(message); - var result = browserBot.nextConfirmResult; - browserBot.nextConfirmResult = true; - self.relayBotToRC("browserbot.recordedConfirmations"); - return result; - }; - - windowToModify.prompt = function(message) { - browserBot.recordedPrompts.push(message); - var result = !browserBot.nextConfirmResult ? null : browserBot.nextPromptResult; - browserBot.nextConfirmResult = true; - browserBot.nextPromptResult = ''; - self.relayBotToRC("browserbot.recordedPrompts"); - return result; - }; - - // Keep a reference to all popup windows by name - // note that in IE the "windowName" argument must be a valid javascript identifier, it seems. - var originalOpen = windowToModify.open; - var originalOpenReference; - if (browserVersion.isHTA) { - originalOpenReference = 'selenium_originalOpen' + new Date().getTime(); - windowToModify[originalOpenReference] = windowToModify.open; - } - - var isHTA = browserVersion.isHTA; - - var newOpen = function(url, windowName, windowFeatures, replaceFlag) { - var myOriginalOpen = originalOpen; - if (isHTA) { - myOriginalOpen = this[originalOpenReference]; - } - var openedWindow = myOriginalOpen(url, windowName, windowFeatures, replaceFlag); - LOG.debug("window.open call intercepted; window ID (which you can use with selectWindow()) is \"" + windowName + "\""); - if (windowName!=null) { - openedWindow["seleniumWindowName"] = windowName; - } - selenium.browserbot.openedWindows[windowName] = openedWindow; - return openedWindow; - }; - - if (browserVersion.isHTA) { - originalOpenReference = 'selenium_originalOpen' + new Date().getTime(); - newOpenReference = 'selenium_newOpen' + new Date().getTime(); - var setOriginalRef = "this['" + originalOpenReference + "'] = this.open;"; - - if (windowToModify.eval) { - windowToModify.eval(setOriginalRef); - windowToModify.open = newOpen; - } else { - // DGF why can't I eval here? Seems like I'm querying the window at a bad time, maybe? - setOriginalRef += "this.open = this['" + newOpenReference + "'];"; - windowToModify[newOpenReference] = newOpen; - windowToModify.setTimeout(setOriginalRef, 0); - } - } else { - windowToModify.open = newOpen; - } -}; - -/** - * Call the supplied function when a the current page unloads and a new one loads. - * This is done by polling continuously until the document changes and is fully loaded. - */ -BrowserBot.prototype.modifySeparateTestWindowToDetectPageLoads = function(windowObject) { - // Since the unload event doesn't fire in Safari 1.3, we start polling immediately - if (!windowObject) { - LOG.warn("modifySeparateTestWindowToDetectPageLoads: no windowObject!"); - return; - } - if (this._windowClosed(windowObject)) { - LOG.info("modifySeparateTestWindowToDetectPageLoads: windowObject was closed"); - return; - } - var oldMarker = this.isPollingForLoad(windowObject); - if (oldMarker) { - LOG.debug("modifySeparateTestWindowToDetectPageLoads: already polling this window: " + oldMarker); - return; - } - - var marker = 'selenium' + new Date().getTime(); - LOG.debug("Starting pollForLoad (" + marker + "): " + windowObject.location); - this.pollingForLoad[marker] = true; - // if this is a frame, add a load listener, otherwise, attach a poller - var frameElement = this._getFrameElement(windowObject); - // DGF HTA mode can't attach load listeners to subframes (yuk!) - var htaSubFrame = this._isHTASubFrame(windowObject); - if (frameElement && !htaSubFrame) { - LOG.debug("modifySeparateTestWindowToDetectPageLoads: this window is a frame; attaching a load listener"); - addLoadListener(frameElement, this.recordPageLoad); - frameElement[marker] = true; - frameElement[this.uniqueId] = marker; - } else { - windowObject.location[marker] = true; - windowObject[this.uniqueId] = marker; - this.pollForLoad(this.recordPageLoad, windowObject, windowObject.document, windowObject.location, windowObject.location.href, marker); - } -}; - -BrowserBot.prototype._isHTASubFrame = function(win) { - if (!browserVersion.isHTA) return false; - // DGF this is wrong! what if "win" isn't the selected window? - return this.isSubFrameSelected; -} - -BrowserBot.prototype._getFrameElement = function(win) { - var frameElement = null; - var caught; - try { - frameElement = win.frameElement; - } catch (e) { - caught = true; - } - if (caught) { - // on IE, checking frameElement in a pop-up results in a "No such interface supported" exception - // but it might have a frame element anyway! - var parentContainsIdenticallyNamedFrame = false; - try { - parentContainsIdenticallyNamedFrame = win.parent.frames[win.name]; - } catch (e) {} // this may fail if access is denied to the parent; in that case, assume it's not a pop-up - - if (parentContainsIdenticallyNamedFrame) { - // it can't be a coincidence that the parent has a frame with the same name as myself! - return BrowserBot.prototype.locateElementByName(win.name, win.parent.document, win.parent); - } - } - return frameElement; -} - -/** - * Set up a polling timer that will keep checking the readyState of the document until it's complete. - * Since we might call this before the original page is unloaded, we first check to see that the current location - * or href is different from the original one. - */ -BrowserBot.prototype.pollForLoad = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { - LOG.debug("pollForLoad original (" + marker + "): " + originalHref); - try { - if (this._windowClosed(windowObject)) { - LOG.debug("pollForLoad WINDOW CLOSED (" + marker + ")"); - delete this.pollingForLoad[marker]; - return; - } - - var isSamePage = this._isSamePage(windowObject, originalDocument, originalLocation, originalHref, marker); - var rs = this.getReadyState(windowObject, windowObject.document); - - if (!isSamePage && rs == 'complete') { - var currentHref = windowObject.location.href; - LOG.debug("pollForLoad FINISHED (" + marker + "): " + rs + " (" + currentHref + ")"); - delete this.pollingForLoad[marker]; - this._modifyWindow(windowObject); - var newMarker = this.isPollingForLoad(windowObject); - if (!newMarker) { - LOG.debug("modifyWindow didn't start new poller: " + newMarker); - this.modifySeparateTestWindowToDetectPageLoads(windowObject); - } - newMarker = this.isPollingForLoad(windowObject); - var currentlySelectedWindow; - var currentlySelectedWindowMarker; - currentlySelectedWindow =this.getCurrentWindow(true); - currentlySelectedWindowMarker = currentlySelectedWindow[this.uniqueId]; - - LOG.debug("pollForLoad (" + marker + ") restarting " + newMarker); - if (/(TestRunner-splash|Blank)\.html\?start=true$/.test(currentHref)) { - LOG.debug("pollForLoad Oh, it's just the starting page. Never mind!"); - } else if (currentlySelectedWindowMarker == newMarker) { - loadFunction(currentlySelectedWindow); - } else { - LOG.debug("pollForLoad page load detected in non-current window; ignoring (currentlySelected="+currentlySelectedWindowMarker+", detection in "+newMarker+")"); - } - return; - } - LOG.debug("pollForLoad continue (" + marker + "): " + currentHref); - this.reschedulePoller(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); - } catch (e) { - LOG.error("Exception during pollForLoad; this should get noticed soon (" + e.message + ")!"); - LOG.exception(e); - this.pageLoadError = e; - } -}; - -BrowserBot.prototype._isSamePage = function(windowObject, originalDocument, originalLocation, originalHref, marker) { - var currentDocument = windowObject.document; - var currentLocation = windowObject.location; - var currentHref = currentLocation.href - - var sameDoc = this._isSameDocument(originalDocument, currentDocument); - - var sameLoc = (originalLocation === currentLocation); - - // hash marks don't meant the page has loaded, so we need to strip them off if they exist... - var currentHash = currentHref.indexOf('#'); - if (currentHash > 0) { - currentHref = currentHref.substring(0, currentHash); - } - var originalHash = originalHref.indexOf('#'); - if (originalHash > 0) { - originalHref = originalHref.substring(0, originalHash); - } - LOG.debug("_isSamePage: currentHref: " + currentHref); - LOG.debug("_isSamePage: originalHref: " + originalHref); - - var sameHref = (originalHref === currentHref); - var markedLoc = currentLocation[marker]; - - if (browserVersion.isKonqueror || browserVersion.isSafari) { - // the mark disappears too early on these browsers - markedLoc = true; - } - - // since this is some _very_ important logic, especially for PI and multiWindow mode, we should log all these out - LOG.debug("_isSamePage: sameDoc: " + sameDoc); - LOG.debug("_isSamePage: sameLoc: " + sameLoc); - LOG.debug("_isSamePage: sameHref: " + sameHref); - LOG.debug("_isSamePage: markedLoc: " + markedLoc); - - return sameDoc && sameLoc && sameHref && markedLoc -}; - -BrowserBot.prototype._isSameDocument = function(originalDocument, currentDocument) { - return originalDocument === currentDocument; -}; - - -BrowserBot.prototype.getReadyState = function(windowObject, currentDocument) { - var rs = currentDocument.readyState; - if (rs == null) { - if ((this.buttonWindow!=null && this.buttonWindow.document.readyState == null) // not proxy injection mode (and therefore buttonWindow isn't null) - || (top.document.readyState == null)) { // proxy injection mode (and therefore everything's in the top window, but buttonWindow doesn't exist) - // uh oh! we're probably on Firefox with no readyState extension installed! - // We'll have to just take a guess as to when the document is loaded; this guess - // will never be perfect. :-( - if (typeof currentDocument.getElementsByTagName != 'undefined' - && typeof currentDocument.getElementById != 'undefined' - && ( currentDocument.getElementsByTagName('body')[0] != null - || currentDocument.body != null )) { - if (windowObject.frameElement && windowObject.location.href == "about:blank" && windowObject.frameElement.src != "about:blank") { - LOG.info("getReadyState not loaded, frame location was about:blank, but frame src = " + windowObject.frameElement.src); - return null; - } - LOG.debug("getReadyState = windowObject.frames.length = " + windowObject.frames.length); - for (var i = 0; i < windowObject.frames.length; i++) { - LOG.debug("i = " + i); - if (this.getReadyState(windowObject.frames[i], windowObject.frames[i].document) != 'complete') { - LOG.debug("getReadyState aha! the nested frame " + windowObject.frames[i].name + " wasn't ready!"); - return null; - } - } - - rs = 'complete'; - } else { - LOG.debug("pollForLoad readyState was null and DOM appeared to not be ready yet"); - } - } - } - else if (rs == "loading" && browserVersion.isIE) { - LOG.debug("pageUnloading = true!!!!"); - this.pageUnloading = true; - } - LOG.debug("getReadyState returning " + rs); - return rs; -}; - -/** This function isn't used normally, but was the way we used to schedule pollers: - asynchronously executed autonomous units. This is deprecated, but remains here - for future reference. - */ -BrowserBot.prototype.XXXreschedulePoller = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { - var self = this; - window.setTimeout(function() { - self.pollForLoad(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); - }, 500); -}; - -/** This function isn't used normally, but is useful for debugging asynchronous pollers - * To enable it, rename it to "reschedulePoller", so it will override the - * existing reschedulePoller function - */ -BrowserBot.prototype.XXXreschedulePoller = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { - var doc = this.buttonWindow.document; - var button = doc.createElement("button"); - var buttonName = doc.createTextNode(marker + " - " + windowObject.name); - button.appendChild(buttonName); - var tools = doc.getElementById("tools"); - var self = this; - button.onclick = function() { - tools.removeChild(button); - self.pollForLoad(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); - }; - tools.appendChild(button); - window.setTimeout(button.onclick, 500); -}; - -BrowserBot.prototype.reschedulePoller = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { - var self = this; - var pollerFunction = function() { - self.pollForLoad(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); - }; - this.windowPollers.push(pollerFunction); -}; - -BrowserBot.prototype.runScheduledPollers = function() { - LOG.debug("runScheduledPollers"); - var oldPollers = this.windowPollers; - this.windowPollers = new Array(); - for (var i = 0; i < oldPollers.length; i++) { - oldPollers[i].call(); - } - LOG.debug("runScheduledPollers DONE"); -}; - -BrowserBot.prototype.isPollingForLoad = function(win) { - var marker; - var frameElement = this._getFrameElement(win); - var htaSubFrame = this._isHTASubFrame(win); - if (frameElement && !htaSubFrame) { - marker = frameElement[this.uniqueId]; - } else { - marker = win[this.uniqueId]; - } - if (!marker) { - LOG.debug("isPollingForLoad false, missing uniqueId " + this.uniqueId + ": " + marker); - return false; - } - if (!this.pollingForLoad[marker]) { - LOG.debug("isPollingForLoad false, this.pollingForLoad[" + marker + "]: " + this.pollingForLoad[marker]); - return false; - } - return marker; -}; - -BrowserBot.prototype.getWindowByName = function(windowName, doNotModify) { - LOG.debug("getWindowByName(" + windowName + ")"); - // First look in the map of opened windows - var targetWindow = this.openedWindows[windowName]; - if (!targetWindow) { - targetWindow = this.topWindow[windowName]; - } - if (!targetWindow && windowName == "_blank") { - for (var winName in this.openedWindows) { - // _blank can match selenium_blank*, if it looks like it's OK (valid href, not closed) - if (/^selenium_blank/.test(winName)) { - targetWindow = this.openedWindows[winName]; - var ok; - try { - if (!this._windowClosed(targetWindow)) { - ok = targetWindow.location.href; - } - } catch (e) {} - if (ok) break; - } - } - } - if (!targetWindow) { - throw new SeleniumError("Window does not exist"); - } - if (browserVersion.isHTA) { - try { - targetWindow.location.href; - } catch (e) { - targetWindow = window.open("", targetWindow.name); - this.openedWindows[targetWindow.name] = targetWindow; - } - } - if (!doNotModify) { - this._modifyWindow(targetWindow); - } - return targetWindow; -}; - -BrowserBot.prototype.getCurrentWindow = function(doNotModify) { - var testWindow = this.currentWindow; - if (!doNotModify) { - this._modifyWindow(testWindow); - if (!this.proxyInjectionMode) { - // In proxy injection mode, have to avoid logging during getCurrentWindow to avoid an infinite loop - LOG.debug("getCurrentWindow newPageLoaded = false"); - } - this.newPageLoaded = false; - } - testWindow = this._handleClosedSubFrame(testWindow, doNotModify); - return testWindow; -}; - -BrowserBot.prototype._handleClosedSubFrame = function(testWindow, doNotModify) { - if (this.proxyInjectionMode) { - return testWindow; - } - - if (this.isSubFrameSelected) { - var missing = true; - if (testWindow.parent && testWindow.parent.frames && testWindow.parent.frames.length) { - for (var i = 0; i < testWindow.parent.frames.length; i++) { - if (testWindow.parent.frames[i] == testWindow) { - missing = false; - break; - } - } - } - if (missing) { - LOG.warn("Current subframe appears to have closed; selecting top frame"); - this.selectFrame("relative=top"); - return this.getCurrentWindow(doNotModify); - } - } else if (this._windowClosed(testWindow)) { - var closedError = new SeleniumError("Current window or frame is closed!"); - closedError.windowClosed = true; - throw closedError; - } - return testWindow; -}; - -BrowserBot.prototype.highlight = function (element, force) { - if (force || this.shouldHighlightLocatedElement) { - try { - highlight(element); - } catch (e) {} // DGF element highlighting is low-priority and possibly dangerous - } - return element; -} - -BrowserBot.prototype.setShouldHighlightElement = function (shouldHighlight) { - this.shouldHighlightLocatedElement = shouldHighlight; -} - -/*****************************************************************/ -/* BROWSER-SPECIFIC FUNCTIONS ONLY AFTER THIS LINE */ - - -BrowserBot.prototype._registerAllLocatorFunctions = function() { - // TODO - don't do this in the constructor - only needed once ever - this.locationStrategies = {}; - for (var functionName in this) { - var result = /^locateElementBy([A-Z].+)$/.exec(functionName); - if (result != null) { - var locatorFunction = this[functionName]; - if (typeof(locatorFunction) != 'function') { - continue; - } - // Use a specified prefix in preference to one generated from - // the function name - var locatorPrefix = locatorFunction.prefix || result[1].toLowerCase(); - this.locationStrategies[locatorPrefix] = locatorFunction; - } - } - - /** - * Find a locator based on a prefix. - */ - this.findElementBy = function(locatorType, locator, inDocument, inWindow) { - var locatorFunction = this.locationStrategies[locatorType]; - if (! locatorFunction) { - throw new SeleniumError("Unrecognised locator type: '" + locatorType + "'"); - } - return locatorFunction.call(this, locator, inDocument, inWindow); - }; - - /** - * The implicit locator, that is used when no prefix is supplied. - */ - this.locationStrategies['implicit'] = function(locator, inDocument, inWindow) { - if (locator.startsWith('//')) { - return this.locateElementByXPath(locator, inDocument, inWindow); - } - if (locator.startsWith('document.')) { - return this.locateElementByDomTraversal(locator, inDocument, inWindow); - } - return this.locateElementByIdentifier(locator, inDocument, inWindow); - }; -} - -BrowserBot.prototype.getDocument = function() { - return this.getCurrentWindow().document; -} - -BrowserBot.prototype.getTitle = function() { - var t = this.getDocument().title; - if (typeof(t) == "string") { - t = t.trim(); - } - return t; -} - -/* - * Finds an element recursively in frames and nested frames - * in the specified document, using various lookup protocols - */ -BrowserBot.prototype.findElementRecursive = function(locatorType, locatorString, inDocument, inWindow) { - - var element = this.findElementBy(locatorType, locatorString, inDocument, inWindow); - if (element != null) { - return element; - } - - for (var i = 0; i < inWindow.frames.length; i++) { - element = this.findElementRecursive(locatorType, locatorString, inWindow.frames[i].document, inWindow.frames[i]); - - if (element != null) { - return element; - } - } -}; - -/* -* Finds an element on the current page, using various lookup protocols -*/ -BrowserBot.prototype.findElement = function(locator) { - var locatorType = 'implicit'; - var locatorString = locator; - - // If there is a locator prefix, use the specified strategy - var result = locator.match(/^([A-Za-z]+)=(.+)/); - if (result) { - locatorType = result[1].toLowerCase(); - locatorString = result[2]; - } - - var element = this.findElementRecursive(locatorType, locatorString, this.getDocument(), this.getCurrentWindow()) - - if (element != null) { - return this.browserbot.highlight(element); - } - - // Element was not found by any locator function. - throw new SeleniumError("Element " + locator + " not found"); -}; - -/** - * In non-IE browsers, getElementById() does not search by name. Instead, we - * we search separately by id and name. - */ -BrowserBot.prototype.locateElementByIdentifier = function(identifier, inDocument, inWindow) { - return BrowserBot.prototype.locateElementById(identifier, inDocument, inWindow) - || BrowserBot.prototype.locateElementByName(identifier, inDocument, inWindow) - || null; -}; - -/** - * Find the element with id - can't rely on getElementById, coz it returns by name as well in IE.. - */ -BrowserBot.prototype.locateElementById = function(identifier, inDocument, inWindow) { - var element = inDocument.getElementById(identifier); - if (element && element.id === identifier) { - return element; - } - else { - return null; - } -}; - -/** - * Find an element by name, refined by (optional) element-filter - * expressions. - */ -BrowserBot.prototype.locateElementByName = function(locator, document, inWindow) { - var elements = document.getElementsByTagName("*"); - - var filters = locator.split(' '); - filters[0] = 'name=' + filters[0]; - - while (filters.length) { - var filter = filters.shift(); - elements = this.selectElements(filter, elements, 'value'); - } - - if (elements.length > 0) { - return elements[0]; - } - return null; -}; - -/** - * Finds an element using by evaluating the specfied string. - */ -BrowserBot.prototype.locateElementByDomTraversal = function(domTraversal, document, window) { - - var browserbot = this.browserbot; - var element = null; - try { - element = eval(domTraversal); - } catch (e) { - e.isSeleniumError = true; - throw e; - } - - if (!element) { - return null; - } - - return element; -}; -BrowserBot.prototype.locateElementByDomTraversal.prefix = "dom"; - -/** - * Finds an element identified by the xpath expression. Expressions _must_ - * begin with "//". - */ -BrowserBot.prototype.locateElementByXPath = function(xpath, inDocument, inWindow) { - - // Trim any trailing "/": not valid xpath, and remains from attribute - // locator. - if (xpath.charAt(xpath.length - 1) == '/') { - xpath = xpath.slice(0, -1); - } - - // Handle //tag - var match = xpath.match(/^\/\/(\w+|\*)$/); - if (match) { - var elements = inDocument.getElementsByTagName(match[1].toUpperCase()); - if (elements == null) return null; - return elements[0]; - } - - // Handle //tag[@attr='value'] - var match = xpath.match(/^\/\/(\w+|\*)\[@(\w+)=('([^\']+)'|"([^\"]+)")\]$/); - if (match) { - // We don't return the value without checking if it is null first. - // This is beacuse in some rare cases, this shortcut actually WONT work - // but that the full XPath WILL. A known case, for example, is in IE - // when the attribute is onclick/onblur/onsubmit/etc. Due to a bug in IE - // this shortcut won't work because the actual function is returned - // by getAttribute() rather than the text of the attribute. - var val = this._findElementByTagNameAndAttributeValue( - inDocument, - match[1].toUpperCase(), - match[2].toLowerCase(), - match[3].slice(1, -1) - ); - if (val) { - return val; - } - } - - // Handle //tag[text()='value'] - var match = xpath.match(/^\/\/(\w+|\*)\[text\(\)=('([^\']+)'|"([^\"]+)")\]$/); - if (match) { - return this._findElementByTagNameAndText( - inDocument, - match[1].toUpperCase(), - match[2].slice(1, -1) - ); - } - - return this._findElementUsingFullXPath(xpath, inDocument); -}; - -BrowserBot.prototype._findElementByTagNameAndAttributeValue = function( - inDocument, tagName, attributeName, attributeValue - ) { - if (browserVersion.isIE && attributeName == "class") { - attributeName = "className"; - } - var elements = inDocument.getElementsByTagName(tagName); - for (var i = 0; i < elements.length; i++) { - var elementAttr = elements[i].getAttribute(attributeName); - if (elementAttr == attributeValue) { - return elements[i]; - } - } - return null; -}; - -BrowserBot.prototype._findElementByTagNameAndText = function( - inDocument, tagName, text - ) { - var elements = inDocument.getElementsByTagName(tagName); - for (var i = 0; i < elements.length; i++) { - if (getText(elements[i]) == text) { - return elements[i]; - } - } - return null; -}; - -BrowserBot.prototype._namespaceResolver = function(prefix) { - if (prefix == 'html' || prefix == 'xhtml' || prefix == 'x') { - return 'http://www.w3.org/1999/xhtml'; - } else if (prefix == 'mathml') { - return 'http://www.w3.org/1998/Math/MathML'; - } else { - throw new Error("Unknown namespace: " + prefix + "."); - } -} - -BrowserBot.prototype._findElementUsingFullXPath = function(xpath, inDocument, inWindow) { - // HUGE hack - remove namespace from xpath for IE - if (browserVersion.isIE) { - xpath = xpath.replace(/x:/g, '') - } - - // Use document.evaluate() if it's available - if (inDocument.evaluate) { - return inDocument.evaluate(xpath, inDocument, this._namespaceResolver, 0, null).iterateNext(); - } - - // If not, fall back to slower JavaScript implementation - var context = new ExprContext(inDocument); - var xpathObj = xpathParse(xpath); - var xpathResult = xpathObj.evaluate(context); - if (xpathResult && xpathResult.value) { - return xpathResult.value[0]; - } - return null; -}; - -/** - * Finds a link element with text matching the expression supplied. Expressions must - * begin with "link:". - */ -BrowserBot.prototype.locateElementByLinkText = function(linkText, inDocument, inWindow) { - var links = inDocument.getElementsByTagName('a'); - for (var i = 0; i < links.length; i++) { - var element = links[i]; - if (PatternMatcher.matches(linkText, getText(element))) { - return element; - } - } - return null; -}; -BrowserBot.prototype.locateElementByLinkText.prefix = "link"; - -/** - * Returns an attribute based on an attribute locator. This is made up of an element locator - * suffixed with @attribute-name. - */ -BrowserBot.prototype.findAttribute = function(locator) { - // Split into locator + attributeName - var attributePos = locator.lastIndexOf("@"); - var elementLocator = locator.slice(0, attributePos); - var attributeName = locator.slice(attributePos + 1); - - // Find the element. - var element = this.findElement(elementLocator); - - // Handle missing "class" attribute in IE. - if (browserVersion.isIE && attributeName == "class") { - attributeName = "className"; - } - - // Get the attribute value. - var attributeValue = element.getAttribute(attributeName); - - return attributeValue ? attributeValue.toString() : null; -}; - -/* -* Select the specified option and trigger the relevant events of the element. -*/ -BrowserBot.prototype.selectOption = function(element, optionToSelect) { - triggerEvent(element, 'focus', false); - var changed = false; - for (var i = 0; i < element.options.length; i++) { - var option = element.options[i]; - if (option.selected && option != optionToSelect) { - option.selected = false; - changed = true; - } - else if (!option.selected && option == optionToSelect) { - option.selected = true; - changed = true; - } - } - - if (changed) { - triggerEvent(element, 'change', true); - } -}; - -/* -* Select the specified option and trigger the relevant events of the element. -*/ -BrowserBot.prototype.addSelection = function(element, option) { - this.checkMultiselect(element); - triggerEvent(element, 'focus', false); - if (!option.selected) { - option.selected = true; - triggerEvent(element, 'change', true); - } -}; - -/* -* Select the specified option and trigger the relevant events of the element. -*/ -BrowserBot.prototype.removeSelection = function(element, option) { - this.checkMultiselect(element); - triggerEvent(element, 'focus', false); - if (option.selected) { - option.selected = false; - triggerEvent(element, 'change', true); - } -}; - -BrowserBot.prototype.checkMultiselect = function(element) { - if (!element.multiple) - { - throw new SeleniumError("Not a multi-select"); - } - -}; - -BrowserBot.prototype.replaceText = function(element, stringValue) { - triggerEvent(element, 'focus', false); - triggerEvent(element, 'select', true); - var maxLengthAttr = element.getAttribute("maxLength"); - var actualValue = stringValue; - if (maxLengthAttr != null) { - var maxLength = parseInt(maxLengthAttr); - if (stringValue.length > maxLength) { - LOG.warn("BEFORE") - actualValue = stringValue.substr(0, maxLength); - LOG.warn("AFTER") - } - } - - if (getTagName(element) == "body") { - if (element.ownerDocument && element.ownerDocument.designMode) { - var designMode = new String(element.ownerDocument.designMode).toLowerCase(); - if (designMode = "on") { - // this must be a rich text control! - element.innerHTML = actualValue; - } - } - } else { - element.value = actualValue; - } - // DGF this used to be skipped in chrome URLs, but no longer. Is xpcnativewrappers to blame? - try { - triggerEvent(element, 'change', true); - } catch (e) {} -}; - -BrowserBot.prototype.submit = function(formElement) { - var actuallySubmit = true; - this._modifyElementTarget(formElement); - if (formElement.onsubmit) { - if (browserVersion.isHTA) { - // run the code in the correct window so alerts are handled correctly even in HTA mode - var win = this.browserbot.getCurrentWindow(); - var now = new Date().getTime(); - var marker = 'marker' + now; - win[marker] = formElement; - win.setTimeout("var actuallySubmit = "+marker+".onsubmit();" + - "if (actuallySubmit) { " + - marker+".submit(); " + - "if ("+marker+".target && !/^_/.test("+marker+".target)) {"+ - "window.open('', "+marker+".target);"+ - "}"+ - "};"+ - marker+"=null", 0); - // pause for up to 2s while this command runs - var terminationCondition = function () { - return !win[marker]; - } - return Selenium.decorateFunctionWithTimeout(terminationCondition, 2000); - } else { - actuallySubmit = formElement.onsubmit(); - if (actuallySubmit) { - formElement.submit(); - if (formElement.target && !/^_/.test(formElement.target)) { - this.browserbot.openWindow('', formElement.target); - } - } - } - } else { - formElement.submit(); - } -} - -BrowserBot.prototype.clickElement = function(element, clientX, clientY) { - this._fireEventOnElement("click", element, clientX, clientY); -}; - -BrowserBot.prototype.doubleClickElement = function(element, clientX, clientY) { - this._fireEventOnElement("dblclick", element, clientX, clientY); -}; - -BrowserBot.prototype._modifyElementTarget = function(element) { - if (element.target) { - if (element.target == "_blank" || /^selenium_blank/.test(element.target) ) { - var tagName = getTagName(element); - if (tagName == "a" || tagName == "form") { - var newTarget = "selenium_blank" + Math.round(100000 * Math.random()); - LOG.warn("Link has target '_blank', which is not supported in Selenium! Randomizing target to be: " + newTarget); - this.browserbot.openWindow('', newTarget); - element.target = newTarget; - } - } - } -} - - -BrowserBot.prototype._handleClickingImagesInsideLinks = function(targetWindow, element) { - if (element.parentNode && element.parentNode.href) { - targetWindow.location.href = element.parentNode.href; - } -} - -BrowserBot.prototype._getTargetWindow = function(element) { - var targetWindow = element.ownerDocument.defaultView; - if (element.target) { - targetWindow = this._getFrameFromGlobal(element.target); - } - return targetWindow; -} - -BrowserBot.prototype._getFrameFromGlobal = function(target) { - - if (target == "_top") { - return this.topFrame; - } else if (target == "_parent") { - return this.getCurrentWindow().parent; - } else if (target == "_blank") { - // TODO should this set cleverer window defaults? - return this.getCurrentWindow().open('', '_blank'); - } - var frameElement = this.findElementBy("implicit", target, this.topFrame.document, this.topFrame); - if (frameElement) { - return frameElement.contentWindow; - } - var win = this.getWindowByName(target); - if (win) return win; - return this.getCurrentWindow().open('', target); -} - - -BrowserBot.prototype.bodyText = function() { - return getText(this.getDocument().body); -}; - -BrowserBot.prototype.getAllButtons = function() { - var elements = this.getDocument().getElementsByTagName('input'); - var result = ''; - - for (var i = 0; i < elements.length; i++) { - if (elements[i].type == 'button' || elements[i].type == 'submit' || elements[i].type == 'reset') { - result += elements[i].id; - - result += ','; - } - } - - return result; -}; - - -BrowserBot.prototype.getAllFields = function() { - var elements = this.getDocument().getElementsByTagName('input'); - var result = ''; - - for (var i = 0; i < elements.length; i++) { - if (elements[i].type == 'text') { - result += elements[i].id; - - result += ','; - } - } - - return result; -}; - -BrowserBot.prototype.getAllLinks = function() { - var elements = this.getDocument().getElementsByTagName('a'); - var result = ''; - - for (var i = 0; i < elements.length; i++) { - result += elements[i].id; - - result += ','; - } - - return result; -}; - -BrowserBot.prototype.setContext = function(strContext, logLevel) { - - //set the current test title - var ctx = document.getElementById("context"); - if (ctx != null) { - ctx.innerHTML = strContext; - } - if (logLevel != null) { - LOG.setLogLevelThreshold(logLevel); - } -}; - -function isDefined(value) { - return typeof(value) != undefined; -} - -BrowserBot.prototype.goBack = function() { - this.getCurrentWindow().history.back(); -}; - -BrowserBot.prototype.goForward = function() { - this.getCurrentWindow().history.forward(); -}; - -BrowserBot.prototype.close = function() { - if (browserVersion.isChrome || browserVersion.isSafari || browserVersion.isOpera) { - this.getCurrentWindow().close(); - } else { - this.getCurrentWindow().eval("window.close();"); - } -}; - -BrowserBot.prototype.refresh = function() { - this.getCurrentWindow().location.reload(true); -}; - -/** - * Refine a list of elements using a filter. - */ -BrowserBot.prototype.selectElementsBy = function(filterType, filter, elements) { - var filterFunction = BrowserBot.filterFunctions[filterType]; - if (! filterFunction) { - throw new SeleniumError("Unrecognised element-filter type: '" + filterType + "'"); - } - - return filterFunction(filter, elements); -}; - -BrowserBot.filterFunctions = {}; - -BrowserBot.filterFunctions.name = function(name, elements) { - var selectedElements = []; - for (var i = 0; i < elements.length; i++) { - if (elements[i].name === name) { - selectedElements.push(elements[i]); - } - } - return selectedElements; -}; - -BrowserBot.filterFunctions.value = function(value, elements) { - var selectedElements = []; - for (var i = 0; i < elements.length; i++) { - if (elements[i].value === value) { - selectedElements.push(elements[i]); - } - } - return selectedElements; -}; - -BrowserBot.filterFunctions.index = function(index, elements) { - index = Number(index); - if (isNaN(index) || index < 0) { - throw new SeleniumError("Illegal Index: " + index); - } - if (elements.length <= index) { - throw new SeleniumError("Index out of range: " + index); - } - return [elements[index]]; -}; - -BrowserBot.prototype.selectElements = function(filterExpr, elements, defaultFilterType) { - - var filterType = (defaultFilterType || 'value'); - - // If there is a filter prefix, use the specified strategy - var result = filterExpr.match(/^([A-Za-z]+)=(.+)/); - if (result) { - filterType = result[1].toLowerCase(); - filterExpr = result[2]; - } - - return this.selectElementsBy(filterType, filterExpr, elements); -}; - -/** - * Find an element by class - */ -BrowserBot.prototype.locateElementByClass = function(locator, document) { - return elementFindFirstMatchingChild(document, - function(element) { - return element.className == locator - } - ); -} - -/** - * Find an element by alt - */ -BrowserBot.prototype.locateElementByAlt = function(locator, document) { - return elementFindFirstMatchingChild(document, - function(element) { - return element.alt == locator - } - ); -} - -/** - * Find an element by css selector - */ -BrowserBot.prototype.locateElementByCss = function(locator, document) { - var elements = cssQuery(locator, document); - if (elements.length != 0) - return elements[0]; - return null; -} - - -/*****************************************************************/ -/* BROWSER-SPECIFIC FUNCTIONS ONLY AFTER THIS LINE */ - -function MozillaBrowserBot(frame) { - BrowserBot.call(this, frame); -} -objectExtend(MozillaBrowserBot.prototype, BrowserBot.prototype); - -function KonquerorBrowserBot(frame) { - BrowserBot.call(this, frame); -} -objectExtend(KonquerorBrowserBot.prototype, BrowserBot.prototype); - -KonquerorBrowserBot.prototype.setIFrameLocation = function(iframe, location) { - // Window doesn't fire onload event when setting src to the current value, - // so we set it to blank first. - iframe.src = "about:blank"; - iframe.src = location; -}; - -KonquerorBrowserBot.prototype.setOpenLocation = function(win, loc) { - // Window doesn't fire onload event when setting src to the current value, - // so we just refresh in that case instead. - loc = absolutify(loc, this.baseUrl); - loc = canonicalize(loc); - var startLoc = parseUrl(win.location.href); - startLoc.hash = null; - var startUrl = reassembleLocation(startLoc); - LOG.debug("startUrl="+startUrl); - LOG.debug("win.location.href="+win.location.href); - LOG.debug("loc="+loc); - if (startUrl == loc) { - LOG.debug("opening exact same location"); - this.refresh(); - } else { - LOG.debug("locations differ"); - win.location.href = loc; - } - // force the current polling thread to detect a page load - var marker = this.isPollingForLoad(win); - if (marker) { - delete win.location[marker]; - } -}; - -KonquerorBrowserBot.prototype._isSameDocument = function(originalDocument, currentDocument) { - // under Konqueror, there may be this case: - // originalDocument and currentDocument are different objects - // while their location are same. - if (originalDocument) { - return originalDocument.location == currentDocument.location - } else { - return originalDocument === currentDocument; - } -}; - -function SafariBrowserBot(frame) { - BrowserBot.call(this, frame); -} -objectExtend(SafariBrowserBot.prototype, BrowserBot.prototype); - -SafariBrowserBot.prototype.setIFrameLocation = KonquerorBrowserBot.prototype.setIFrameLocation; -SafariBrowserBot.prototype.setOpenLocation = KonquerorBrowserBot.prototype.setOpenLocation; - - -function OperaBrowserBot(frame) { - BrowserBot.call(this, frame); -} -objectExtend(OperaBrowserBot.prototype, BrowserBot.prototype); -OperaBrowserBot.prototype.setIFrameLocation = function(iframe, location) { - if (iframe.src == location) { - iframe.src = location + '?reload'; - } else { - iframe.src = location; - } -} - -function IEBrowserBot(frame) { - BrowserBot.call(this, frame); -} -objectExtend(IEBrowserBot.prototype, BrowserBot.prototype); - -IEBrowserBot.prototype._handleClosedSubFrame = function(testWindow, doNotModify) { - if (this.proxyInjectionMode) { - return testWindow; - } - - try { - testWindow.location.href; - this.permDenied = 0; - } catch (e) { - this.permDenied++; - } - if (this._windowClosed(testWindow) || this.permDenied > 4) { - if (this.isSubFrameSelected) { - LOG.warn("Current subframe appears to have closed; selecting top frame"); - this.selectFrame("relative=top"); - return this.getCurrentWindow(doNotModify); - } else { - var closedError = new SeleniumError("Current window or frame is closed!"); - closedError.windowClosed = true; - throw closedError; - } - } - return testWindow; -}; - -IEBrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { - BrowserBot.prototype.modifyWindowToRecordPopUpDialogs(windowToModify, browserBot); - - // we will call the previous version of this method from within our own interception - oldShowModalDialog = windowToModify.showModalDialog; - - windowToModify.showModalDialog = function(url, args, features) { - // Get relative directory to where TestRunner.html lives - // A risky assumption is that the user's TestRunner is named TestRunner.html - var doc_location = document.location.toString(); - var end_of_base_ref = doc_location.indexOf('TestRunner.html'); - var base_ref = doc_location.substring(0, end_of_base_ref); - - var fullURL = base_ref + "TestRunner.html?singletest=" + escape(browserBot.modalDialogTest) + "&autoURL=" + escape(url) + "&runInterval=" + runOptions.runInterval; - browserBot.modalDialogTest = null; - - var returnValue = oldShowModalDialog(fullURL, args, features); - return returnValue; - }; -}; - -IEBrowserBot.prototype.modifySeparateTestWindowToDetectPageLoads = function(windowObject) { - this.pageUnloading = false; - var self = this; - var pageUnloadDetector = function() { - self.pageUnloading = true; - }; - windowObject.attachEvent("onbeforeunload", pageUnloadDetector); - BrowserBot.prototype.modifySeparateTestWindowToDetectPageLoads.call(this, windowObject); -}; - -IEBrowserBot.prototype.pollForLoad = function(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker) { - LOG.debug("IEBrowserBot.pollForLoad: " + marker); - if (!this.permDeniedCount[marker]) this.permDeniedCount[marker] = 0; - BrowserBot.prototype.pollForLoad.call(this, loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); - if (this.pageLoadError) { - if (this.pageUnloading) { - var self = this; - LOG.warn("pollForLoad UNLOADING (" + marker + "): caught exception while firing events on unloading page: " + this.pageLoadError.message); - this.reschedulePoller(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); - this.pageLoadError = null; - return; - } else if (((this.pageLoadError.message == "Permission denied") || (/^Access is denied/.test(this.pageLoadError.message))) - && this.permDeniedCount[marker]++ < 8) { - if (this.permDeniedCount[marker] > 4) { - var canAccessThisWindow; - var canAccessCurrentlySelectedWindow; - try { - windowObject.location.href; - canAccessThisWindow = true; - } catch (e) {} - try { - this.getCurrentWindow(true).location.href; - canAccessCurrentlySelectedWindow = true; - } catch (e) {} - if (canAccessCurrentlySelectedWindow & !canAccessThisWindow) { - LOG.warn("pollForLoad (" + marker + ") ABORTING: " + this.pageLoadError.message + " (" + this.permDeniedCount[marker] + "), but the currently selected window is fine"); - // returning without rescheduling - this.pageLoadError = null; - return; - } - } - - var self = this; - LOG.warn("pollForLoad (" + marker + "): " + this.pageLoadError.message + " (" + this.permDeniedCount[marker] + "), waiting to see if it goes away"); - this.reschedulePoller(loadFunction, windowObject, originalDocument, originalLocation, originalHref, marker); - this.pageLoadError = null; - return; - } - //handy for debugging! - //throw this.pageLoadError; - } -}; - -IEBrowserBot.prototype._windowClosed = function(win) { - try { - var c = win.closed; - // frame windows claim to be non-closed when their parents are closed - // but you can't access their document objects in that case - if (!c) { - try { - win.document; - } catch (de) { - if (de.message == "Permission denied") { - // the window is probably unloading, which means it's probably not closed yet - return false; - } - else if (/^Access is denied/.test(de.message)) { - // rare variation on "Permission denied"? - LOG.debug("IEBrowserBot.windowClosed: got " + de.message + " (this.pageUnloading=" + this.pageUnloading + "); assuming window is unloading, probably not closed yet"); - return false; - } else { - // this is probably one of those frame window situations - LOG.debug("IEBrowserBot.windowClosed: couldn't read win.document, assume closed: " + de.message + " (this.pageUnloading=" + this.pageUnloading + ")"); - return true; - } - } - } - if (c == null) { - LOG.debug("IEBrowserBot.windowClosed: win.closed was null, assuming closed"); - return true; - } - return c; - } catch (e) { - LOG.debug("IEBrowserBot._windowClosed: Got an exception trying to read win.closed; we'll have to take a guess!"); - - if (browserVersion.isHTA) { - if (e.message == "Permission denied") { - // the window is probably unloading, which means it's not closed yet - return false; - } else { - // there's a good chance that we've lost contact with the window object if it is closed - return true; - } - } else { - // the window is probably unloading, which means it's not closed yet - return false; - } - } -}; - -/** - * In IE, getElementById() also searches by name - this is an optimisation for IE. - */ -IEBrowserBot.prototype.locateElementByIdentifer = function(identifier, inDocument, inWindow) { - return inDocument.getElementById(identifier); -}; - -SafariBrowserBot.prototype.modifyWindowToRecordPopUpDialogs = function(windowToModify, browserBot) { - BrowserBot.prototype.modifyWindowToRecordPopUpDialogs(windowToModify, browserBot); - - var originalOpen = windowToModify.open; - /* - * Safari seems to be broken, so that when we manually trigger the onclick method - * of a button/href, any window.open calls aren't resolved relative to the app location. - * So here we replace the open() method with one that does resolve the url correctly. - */ - windowToModify.open = function(url, windowName, windowFeatures, replaceFlag) { - - if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("/")) { - return originalOpen(url, windowName, windowFeatures, replaceFlag); - } - - // Reduce the current path to the directory - var currentPath = windowToModify.location.pathname || "/"; - currentPath = currentPath.replace(/\/[^\/]*$/, "/"); - - // Remove any leading "./" from the new url. - url = url.replace(/^\.\//, ""); - - newUrl = currentPath + url; - - var openedWindow = originalOpen(newUrl, windowName, windowFeatures, replaceFlag); - LOG.debug("window.open call intercepted; window ID (which you can use with selectWindow()) is \"" + windowName + "\""); - if (windowName!=null) { - openedWindow["seleniumWindowName"] = windowName; - } - return openedWindow; - }; -}; - -MozillaBrowserBot.prototype._fireEventOnElement = function(eventType, element, clientX, clientY) { - var win = this.getCurrentWindow(); - triggerEvent(element, 'focus', false); - - // Add an event listener that detects if the default action has been prevented. - // (This is caused by a javascript onclick handler returning false) - // we capture the whole event, rather than the getPreventDefault() state at the time, - // because we need to let the entire event bubbling and capturing to go through - // before making a decision on whether we should force the href - var savedEvent = null; - - element.addEventListener(eventType, function(evt) { - savedEvent = evt; - }, false); - - this._modifyElementTarget(element); - - // Trigger the event. - this.browserbot.triggerMouseEvent(element, eventType, true, clientX, clientY); - - if (this._windowClosed(win)) { - return; - } - - // Perform the link action if preventDefault was set. - // In chrome URL, the link action is already executed by triggerMouseEvent. - if (!browserVersion.isChrome && savedEvent != null && !savedEvent.getPreventDefault()) { - var targetWindow = this.browserbot._getTargetWindow(element); - if (element.href) { - targetWindow.location.href = element.href; - } else { - this.browserbot._handleClickingImagesInsideLinks(targetWindow, element); - } - } - -}; - - -OperaBrowserBot.prototype._fireEventOnElement = function(eventType, element, clientX, clientY) { - var win = this.getCurrentWindow(); - triggerEvent(element, 'focus', false); - - this._modifyElementTarget(element); - - // Trigger the click event. - this.browserbot.triggerMouseEvent(element, eventType, true, clientX, clientY); - - if (this._windowClosed(win)) { - return; - } - -}; - - -KonquerorBrowserBot.prototype._fireEventOnElement = function(eventType, element, clientX, clientY) { - var win = this.getCurrentWindow(); - triggerEvent(element, 'focus', false); - - this._modifyElementTarget(element); - - if (element[eventType]) { - element[eventType](); - } - else { - this.browserbot.triggerMouseEvent(element, eventType, true, clientX, clientY); - } - - if (this._windowClosed(win)) { - return; - } - -}; - -SafariBrowserBot.prototype._fireEventOnElement = function(eventType, element, clientX, clientY) { - triggerEvent(element, 'focus', false); - var wasChecked = element.checked; - - this._modifyElementTarget(element); - - // For form element it is simple. - if (element[eventType]) { - element[eventType](); - } - // For links and other elements, event emulation is required. - else { - var targetWindow = this.browserbot._getTargetWindow(element); - // todo: deal with anchors? - this.browserbot.triggerMouseEvent(element, eventType, true, clientX, clientY); - - } - -}; - -SafariBrowserBot.prototype.refresh = function() { - var win = this.getCurrentWindow(); - if (win.location.hash) { - // DGF Safari refuses to refresh when there's a hash symbol in the URL - win.location.hash = ""; - var actuallyReload = function() { - win.location.reload(true); - } - window.setTimeout(actuallyReload, 1); - } else { - win.location.reload(true); - } -}; - -IEBrowserBot.prototype._fireEventOnElement = function(eventType, element, clientX, clientY) { - var win = this.getCurrentWindow(); - triggerEvent(element, 'focus', false); - - var wasChecked = element.checked; - - // Set a flag that records if the page will unload - this isn't always accurate, because - // <a href="javascript:alert('foo'):"> triggers the onbeforeunload event, even thought the page won't unload - var pageUnloading = false; - var pageUnloadDetector = function() { - pageUnloading = true; - }; - win.attachEvent("onbeforeunload", pageUnloadDetector); - this._modifyElementTarget(element); - if (element[eventType]) { - element[eventType](); - } - else { - this.browserbot.triggerMouseEvent(element, eventType, true, clientX, clientY); - } - - - // If the page is going to unload - still attempt to fire any subsequent events. - // However, we can't guarantee that the page won't unload half way through, so we need to handle exceptions. - try { - win.detachEvent("onbeforeunload", pageUnloadDetector); - - if (this._windowClosed(win)) { - return; - } - - // Onchange event is not triggered automatically in IE. - if (isDefined(element.checked) && wasChecked != element.checked) { - triggerEvent(element, 'change', true); - } - - } - catch (e) { - // If the page is unloading, we may get a "Permission denied" or "Unspecified error". - // Just ignore it, because the document may have unloaded. - if (pageUnloading) { - LOG.logHook = function() { - }; - LOG.warn("Caught exception when firing events on unloading page: " + e.message); - return; - } - throw e; - } -}; diff --git a/tests/test_tools/selenium/core/scripts/selenium-browserdetect.js b/tests/test_tools/selenium/core/scripts/selenium-browserdetect.js deleted file mode 100644 index a9607371..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-browserdetect.js +++ /dev/null @@ -1,142 +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. - * - */ - -// Although it's generally better web development practice not to use -// browser-detection (feature detection is better), the subtle browser -// differences that Selenium has to work around seem to make it -// necessary. Maybe as we learn more about what we need, we can do this in -// a more "feature-centric" rather than "browser-centric" way. - -var BrowserVersion = function() { - this.name = navigator.appName; - - if (window.opera != null) { - this.browser = BrowserVersion.OPERA; - this.isOpera = true; - return; - } - - var _getQueryParameter = function(searchKey) { - var str = location.search.substr(1); - 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; - }; - - var self = this; - - var checkChrome = function() { - var loc = window.document.location.href; - try { - loc = window.top.document.location.href; - if (/^chrome:\/\//.test(loc)) { - self.isChrome = true; - } else { - self.isChrome = false; - } - } catch (e) { - // can't see the top (that means we might be chrome, but it's impossible to be sure) - self.isChromeDetectable = "no, top location couldn't be read in this window"; - if (_getQueryParameter('thisIsChrome')) { - self.isChrome = true; - } else { - self.isChrome = false; - } - } - - - } - - - - if (this.name == "Microsoft Internet Explorer") { - this.browser = BrowserVersion.IE; - this.isIE = true; - try { - if (window.top.SeleniumHTARunner && window.top.document.location.pathname.match(/.hta$/i)) { - this.isHTA = true; - } - } catch (e) { - this.isHTADetectable = "no, top location couldn't be read in this window"; - if (_getQueryParameter('thisIsHTA')) { - self.isHTA = true; - } else { - self.isHTA = false; - } - } - if ("0" == navigator.appMinorVersion) { - this.preSV1 = true; - if (navigator.appVersion.match(/MSIE 6.0/)) { - this.appearsToBeBrokenInitialIE6 = true; - } - } - return; - } - - if (navigator.userAgent.indexOf('Safari') != -1) { - this.browser = BrowserVersion.SAFARI; - this.isSafari = true; - this.khtml = true; - return; - } - - if (navigator.userAgent.indexOf('Konqueror') != -1) { - this.browser = BrowserVersion.KONQUEROR; - this.isKonqueror = true; - this.khtml = true; - return; - } - - if (navigator.userAgent.indexOf('Firefox') != -1) { - this.browser = BrowserVersion.FIREFOX; - this.isFirefox = true; - this.isGecko = true; - var result = /.*Firefox\/([\d\.]+).*/.exec(navigator.userAgent); - if (result) { - this.firefoxVersion = result[1]; - } - checkChrome(); - return; - } - - if (navigator.userAgent.indexOf('Gecko') != -1) { - this.browser = BrowserVersion.MOZILLA; - this.isMozilla = true; - this.isGecko = true; - checkChrome(); - return; - } - - this.browser = BrowserVersion.UNKNOWN; -} - -BrowserVersion.OPERA = "Opera"; -BrowserVersion.IE = "IE"; -BrowserVersion.KONQUEROR = "Konqueror"; -BrowserVersion.SAFARI = "Safari"; -BrowserVersion.FIREFOX = "Firefox"; -BrowserVersion.MOZILLA = "Mozilla"; -BrowserVersion.UNKNOWN = "Unknown"; - -var browserVersion = new BrowserVersion(); diff --git a/tests/test_tools/selenium/core/scripts/selenium-commandhandlers.js b/tests/test_tools/selenium/core/scripts/selenium-commandhandlers.js deleted file mode 100644 index a23e9335..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-commandhandlers.js +++ /dev/null @@ -1,375 +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. -*/ - -// A naming convention used in this file: -// -// -// - a "seleniumApi" is an instance of the Selenium object, defined in selenium-api.js. -// -// - a "Method" is an unbound function whose target must be supplied when it's called, ie. -// it should be invoked using Function.call() or Function.apply() -// -// - a "Block" is a function that has been bound to a target object, so can be called invoked directly -// (or with a null target) -// -// - "CommandHandler" is effectively an abstract base for -// various handlers including ActionHandler, AccessorHandler and AssertHandler. -// Subclasses need to implement an execute(seleniumApi, command) function, -// where seleniumApi is the Selenium object, and command a SeleniumCommand object. -// -// - Handlers will return a "result" object (ActionResult, AccessorResult, AssertResult). -// ActionResults may contain a .terminationCondition function which is run by -// -executionloop.js after the command is run; we'll run it over and over again -// until it returns true or the .terminationCondition throws an exception. -// AccessorResults will contain the results of running getter (e.g. getTitle returns -// the title as a string). - -var CommandHandlerFactory = classCreate(); -objectExtend(CommandHandlerFactory.prototype, { - - initialize: function() { - this.handlers = {}; - }, - - registerAction: function(name, actionBlock, wait, dontCheckAlertsAndConfirms) { - this.handlers[name] = new ActionHandler(actionBlock, wait, dontCheckAlertsAndConfirms); - }, - - registerAccessor: function(name, accessBlock) { - this.handlers[name] = new AccessorHandler(accessBlock); - }, - - registerAssert: function(name, assertBlock, haltOnFailure) { - this.handlers[name] = new AssertHandler(assertBlock, haltOnFailure); - }, - - getCommandHandler: function(name) { - return this.handlers[name]; - }, - - _registerAllAccessors: function(seleniumApi) { - // Methods of the form getFoo(target) result in commands: - // getFoo, assertFoo, verifyFoo, assertNotFoo, verifyNotFoo - // storeFoo, waitForFoo, and waitForNotFoo. - for (var functionName in seleniumApi) { - var match = /^(get|is)([A-Z].+)$/.exec(functionName); - if (match) { - var accessMethod = seleniumApi[functionName]; - var accessBlock = fnBind(accessMethod, seleniumApi); - var baseName = match[2]; - var isBoolean = (match[1] == "is"); - var requiresTarget = (accessMethod.length == 1); - - this.registerAccessor(functionName, accessBlock); - this._registerStoreCommandForAccessor(baseName, accessBlock, requiresTarget); - - var predicateBlock = this._predicateForAccessor(accessBlock, requiresTarget, isBoolean); - this._registerAssertionsForPredicate(baseName, predicateBlock); - this._registerWaitForCommandsForPredicate(seleniumApi, baseName, predicateBlock); - } - } - }, - - _registerAllActions: function(seleniumApi) { - for (var functionName in seleniumApi) { - var match = /^do([A-Z].+)$/.exec(functionName); - if (match) { - var actionName = match[1].lcfirst(); - var actionMethod = seleniumApi[functionName]; - var dontCheckPopups = actionMethod.dontCheckAlertsAndConfirms; - var actionBlock = fnBind(actionMethod, seleniumApi); - this.registerAction(actionName, actionBlock, false, dontCheckPopups); - this.registerAction(actionName + "AndWait", actionBlock, true, dontCheckPopups); - } - } - }, - - _registerAllAsserts: function(seleniumApi) { - for (var functionName in seleniumApi) { - var match = /^assert([A-Z].+)$/.exec(functionName); - if (match) { - var assertBlock = fnBind(seleniumApi[functionName], seleniumApi); - - // Register the assert with the "assert" prefix, and halt on failure. - var assertName = functionName; - this.registerAssert(assertName, assertBlock, true); - - // Register the assert with the "verify" prefix, and do not halt on failure. - var verifyName = "verify" + match[1]; - this.registerAssert(verifyName, assertBlock, false); - } - } - }, - - registerAll: function(seleniumApi) { - this._registerAllAccessors(seleniumApi); - this._registerAllActions(seleniumApi); - this._registerAllAsserts(seleniumApi); - }, - - _predicateForAccessor: function(accessBlock, requiresTarget, isBoolean) { - if (isBoolean) { - return this._predicateForBooleanAccessor(accessBlock); - } - if (requiresTarget) { - return this._predicateForSingleArgAccessor(accessBlock); - } - return this._predicateForNoArgAccessor(accessBlock); - }, - - _predicateForSingleArgAccessor: function(accessBlock) { - // Given an accessor function getBlah(target), - // return a "predicate" equivalient to isBlah(target, value) that - // is true when the value returned by the accessor matches the specified value. - return function(target, value) { - var accessorResult = accessBlock(target); - if (PatternMatcher.matches(value, accessorResult)) { - return new PredicateResult(true, "Actual value '" + accessorResult + "' did match '" + value + "'"); - } else { - return new PredicateResult(false, "Actual value '" + accessorResult + "' did not match '" + value + "'"); - } - }; - }, - - _predicateForNoArgAccessor: function(accessBlock) { - // Given a (no-arg) accessor function getBlah(), - // return a "predicate" equivalient to isBlah(value) that - // is true when the value returned by the accessor matches the specified value. - return function(value) { - var accessorResult = accessBlock(); - if (PatternMatcher.matches(value, accessorResult)) { - return new PredicateResult(true, "Actual value '" + accessorResult + "' did match '" + value + "'"); - } else { - return new PredicateResult(false, "Actual value '" + accessorResult + "' did not match '" + value + "'"); - } - }; - }, - - _predicateForBooleanAccessor: function(accessBlock) { - // Given a boolean accessor function isBlah(), - // return a "predicate" equivalient to isBlah() that - // returns an appropriate PredicateResult value. - return function() { - var accessorResult; - if (arguments.length > 2) throw new SeleniumError("Too many arguments! " + arguments.length); - if (arguments.length == 2) { - accessorResult = accessBlock(arguments[0], arguments[1]); - } else if (arguments.length == 1) { - accessorResult = accessBlock(arguments[0]); - } else { - accessorResult = accessBlock(); - } - if (accessorResult) { - return new PredicateResult(true, "true"); - } else { - return new PredicateResult(false, "false"); - } - }; - }, - - _invertPredicate: function(predicateBlock) { - // Given a predicate, return the negation of that predicate. - // Leaves the message unchanged. - // Used to create assertNot, verifyNot, and waitForNot commands. - return function(target, value) { - var result = predicateBlock(target, value); - result.isTrue = !result.isTrue; - return result; - }; - }, - - createAssertionFromPredicate: function(predicateBlock) { - // Convert an isBlahBlah(target, value) function into an assertBlahBlah(target, value) function. - return function(target, value) { - var result = predicateBlock(target, value); - if (!result.isTrue) { - Assert.fail(result.message); - } - }; - }, - - _invertPredicateName: function(baseName) { - var matchResult = /^(.*)Present$/.exec(baseName); - if (matchResult != null) { - return matchResult[1] + "NotPresent"; - } - return "Not" + baseName; - }, - - _registerAssertionsForPredicate: function(baseName, predicateBlock) { - // Register an assertion, a verification, a negative assertion, - // and a negative verification based on the specified accessor. - var assertBlock = this.createAssertionFromPredicate(predicateBlock); - this.registerAssert("assert" + baseName, assertBlock, true); - this.registerAssert("verify" + baseName, assertBlock, false); - - var invertedPredicateBlock = this._invertPredicate(predicateBlock); - var negativeassertBlock = this.createAssertionFromPredicate(invertedPredicateBlock); - this.registerAssert("assert" + this._invertPredicateName(baseName), negativeassertBlock, true); - this.registerAssert("verify" + this._invertPredicateName(baseName), negativeassertBlock, false); - }, - - _waitForActionForPredicate: function(predicateBlock) { - // Convert an isBlahBlah(target, value) function into a waitForBlahBlah(target, value) function. - return function(target, value) { - var terminationCondition = function () { - try { - return predicateBlock(target, value).isTrue; - } catch (e) { - // Treat exceptions as meaning the condition is not yet met. - // Useful, for example, for waitForValue when the element has - // not even been created yet. - // TODO: possibly should rethrow some types of exception. - return false; - } - }; - return Selenium.decorateFunctionWithTimeout(terminationCondition, this.defaultTimeout); - }; - }, - - _registerWaitForCommandsForPredicate: function(seleniumApi, baseName, predicateBlock) { - // Register a waitForBlahBlah and waitForNotBlahBlah based on the specified accessor. - var waitForActionMethod = this._waitForActionForPredicate(predicateBlock); - var waitForActionBlock = fnBind(waitForActionMethod, seleniumApi); - - var invertedPredicateBlock = this._invertPredicate(predicateBlock); - var waitForNotActionMethod = this._waitForActionForPredicate(invertedPredicateBlock); - var waitForNotActionBlock = fnBind(waitForNotActionMethod, seleniumApi); - - this.registerAction("waitFor" + baseName, waitForActionBlock, false, true); - this.registerAction("waitFor" + this._invertPredicateName(baseName), waitForNotActionBlock, false, true); - //TODO decide remove "waitForNot.*Present" action name or not - //for the back compatiblity issues we still make waitForNot.*Present availble - this.registerAction("waitForNot" + baseName, waitForNotActionBlock, false, true); - }, - - _registerStoreCommandForAccessor: function(baseName, accessBlock, requiresTarget) { - var action; - if (requiresTarget) { - action = function(target, varName) { - storedVars[varName] = accessBlock(target); - }; - } else { - action = function(varName) { - storedVars[varName] = accessBlock(); - }; - } - this.registerAction("store" + baseName, action, false, true); - } - -}); - -function PredicateResult(isTrue, message) { - this.isTrue = isTrue; - this.message = message; -} - -// NOTE: The CommandHandler is effectively an abstract base for -// various handlers including ActionHandler, AccessorHandler and AssertHandler. -// Subclasses need to implement an execute(seleniumApi, command) function, -// where seleniumApi is the Selenium object, and command a SeleniumCommand object. -function CommandHandler(type, haltOnFailure) { - this.type = type; - this.haltOnFailure = haltOnFailure; -} - -// An ActionHandler is a command handler that executes the sepcified action, -// possibly checking for alerts and confirmations (if checkAlerts is set), and -// possibly waiting for a page load if wait is set. -function ActionHandler(actionBlock, wait, dontCheckAlerts) { - this.actionBlock = actionBlock; - CommandHandler.call(this, "action", true); - if (wait) { - this.wait = true; - } - // note that dontCheckAlerts could be undefined!!! - this.checkAlerts = (dontCheckAlerts) ? false : true; -} -ActionHandler.prototype = new CommandHandler; -ActionHandler.prototype.execute = function(seleniumApi, command) { - if (this.checkAlerts && (null == /(Alert|Confirmation)(Not)?Present/.exec(command.command))) { - // todo: this conditional logic is ugly - seleniumApi.ensureNoUnhandledPopups(); - } - var terminationCondition = this.actionBlock(command.target, command.value); - // If the handler didn't return a wait flag, check to see if the - // handler was registered with the wait flag. - if (terminationCondition == undefined && this.wait) { - terminationCondition = seleniumApi.makePageLoadCondition(); - } - return new ActionResult(terminationCondition); -}; - -function ActionResult(terminationCondition) { - this.terminationCondition = terminationCondition; -} - -function AccessorHandler(accessBlock) { - this.accessBlock = accessBlock; - CommandHandler.call(this, "accessor", true); -} -AccessorHandler.prototype = new CommandHandler; -AccessorHandler.prototype.execute = function(seleniumApi, command) { - var returnValue = this.accessBlock(command.target, command.value); - return new AccessorResult(returnValue); -}; - -function AccessorResult(result) { - this.result = result; -} - -/** - * Handler for assertions and verifications. - */ -function AssertHandler(assertBlock, haltOnFailure) { - this.assertBlock = assertBlock; - CommandHandler.call(this, "assert", haltOnFailure || false); -} -AssertHandler.prototype = new CommandHandler; -AssertHandler.prototype.execute = function(seleniumApi, command) { - var result = new AssertResult(); - try { - this.assertBlock(command.target, command.value); - } catch (e) { - // If this is not a AssertionFailedError, or we should haltOnFailure, rethrow. - if (!e.isAssertionFailedError) { - throw e; - } - if (this.haltOnFailure) { - var error = new SeleniumError(e.failureMessage); - throw error; - } - result.setFailed(e.failureMessage); - } - return result; -}; - -function AssertResult() { - this.passed = true; -} -AssertResult.prototype.setFailed = function(message) { - this.passed = null; - this.failed = true; - this.failureMessage = message; -} - -function SeleniumCommand(command, target, value, isBreakpoint) { - this.command = command; - this.target = target; - this.value = value; - this.isBreakpoint = isBreakpoint; -} - diff --git a/tests/test_tools/selenium/core/scripts/selenium-executionloop.js b/tests/test_tools/selenium/core/scripts/selenium-executionloop.js deleted file mode 100644 index be54115e..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-executionloop.js +++ /dev/null @@ -1,177 +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. -*/ - -function TestLoop(commandFactory) { - this.commandFactory = commandFactory; -} - -TestLoop.prototype = { - - start : function() { - selenium.reset(); - LOG.debug("currentTest.start()"); - this.continueTest(); - }, - - continueTest : function() { - /** - * Select the next command and continue the test. - */ - LOG.debug("currentTest.continueTest() - acquire the next command"); - if (! this.aborted) { - this.currentCommand = this.nextCommand(); - } - if (! this.requiresCallBack) { - this.continueTestAtCurrentCommand(); - } // otherwise, just finish and let the callback invoke continueTestAtCurrentCommand() - }, - - continueTestAtCurrentCommand : function() { - LOG.debug("currentTest.continueTestAtCurrentCommand()"); - if (this.currentCommand) { - // TODO: rename commandStarted to commandSelected, OR roll it into nextCommand - this.commandStarted(this.currentCommand); - this._resumeAfterDelay(); - } else { - this._testComplete(); - } - }, - - _resumeAfterDelay : function() { - /** - * Pause, then execute the current command. - */ - - // Get the command delay. If a pauseInterval is set, use it once - // and reset it. Otherwise, use the defined command-interval. - var delay = this.pauseInterval || this.getCommandInterval(); - this.pauseInterval = undefined; - - if (this.currentCommand.isBreakpoint || delay < 0) { - // Pause: enable the "next/continue" button - this.pause(); - } else { - window.setTimeout(fnBind(this.resume, this), delay); - } - }, - - resume: function() { - /** - * Select the next command and continue the test. - */ - LOG.debug("currentTest.resume() - actually execute"); - try { - selenium.browserbot.runScheduledPollers(); - this._executeCurrentCommand(); - this.continueTestWhenConditionIsTrue(); - } catch (e) { - if (!this._handleCommandError(e)) { - this._testComplete(); - } else { - this.continueTest(); - } - } - }, - - _testComplete : function() { - selenium.ensureNoUnhandledPopups(); - this.testComplete(); - }, - - _executeCurrentCommand : function() { - /** - * Execute the current command. - * - * @return a function which will be used to determine when - * execution can continue, or null if we can continue immediately - */ - var command = this.currentCommand; - LOG.info("Executing: |" + command.command + " | " + command.target + " | " + command.value + " |"); - - var handler = this.commandFactory.getCommandHandler(command.command); - if (handler == null) { - throw new SeleniumError("Unknown command: '" + command.command + "'"); - } - - command.target = selenium.preprocessParameter(command.target); - command.value = selenium.preprocessParameter(command.value); - LOG.debug("Command found, going to execute " + command.command); - this.result = handler.execute(selenium, command); - - - this.waitForCondition = this.result.terminationCondition; - - }, - - _handleCommandError : function(e) { - if (!e.isSeleniumError) { - LOG.exception(e); - var msg = "Selenium failure. Please report to selenium-dev@openqa.org, with error details from the log window."; - if (e.message) { - msg += " The error message is: " + e.message; - } - return this.commandError(msg); - } else { - LOG.error(e.message); - return this.commandError(e.message); - } - }, - - continueTestWhenConditionIsTrue: function () { - /** - * Busy wait for waitForCondition() to become true, and then carry - * on with test. Fail the current test if there's a timeout or an - * exception. - */ - //LOG.debug("currentTest.continueTestWhenConditionIsTrue()"); - selenium.browserbot.runScheduledPollers(); - try { - if (this.waitForCondition == null) { - LOG.debug("null condition; let's continueTest()"); - LOG.debug("Command complete"); - this.commandComplete(this.result); - this.continueTest(); - } else if (this.waitForCondition()) { - LOG.debug("condition satisfied; let's continueTest()"); - this.waitForCondition = null; - LOG.debug("Command complete"); - this.commandComplete(this.result); - this.continueTest(); - } else { - //LOG.debug("waitForCondition was false; keep waiting!"); - window.setTimeout(fnBind(this.continueTestWhenConditionIsTrue, this), 10); - } - } catch (e) { - this.result = {}; - this.result.failed = true; - this.result.failureMessage = extractExceptionMessage(e); - this.commandComplete(this.result); - this.continueTest(); - } - }, - - pause : function() {}, - nextCommand : function() {}, - commandStarted : function() {}, - commandComplete : function() {}, - commandError : function() {}, - testComplete : function() {}, - - getCommandInterval : function() { - return 0; - } - -} diff --git a/tests/test_tools/selenium/core/scripts/selenium-logging.js b/tests/test_tools/selenium/core/scripts/selenium-logging.js deleted file mode 100644 index 6dac9518..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-logging.js +++ /dev/null @@ -1,139 +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. - */ - -var Logger = function() { - this.logWindow = null; -} -Logger.prototype = { - - pendingMessages: new Array(), - - setLogLevelThreshold: function(logLevel) { - this.pendingLogLevelThreshold = logLevel; - this.show(); - // NOTE: log messages will be discarded until the log window is - // fully loaded. - }, - - getLogWindow: function() { - if (this.logWindow && this.logWindow.closed) { - this.logWindow = null; - } - if (this.logWindow && this.pendingLogLevelThreshold && this.logWindow.setThresholdLevel) { - this.logWindow.setThresholdLevel(this.pendingLogLevelThreshold); - - // can't just directly log because that action would loop back - // to this code infinitely - var pendingMessage = new LogMessage("info", "Log level programmatically set to " + this.pendingLogLevelThreshold + " (presumably by driven-mode test code)"); - this.pendingMessages.push(pendingMessage); - - this.pendingLogLevelThreshold = null; // let's only go this way one time - } - - return this.logWindow; - }, - - openLogWindow: function() { - this.logWindow = window.open( - getDocumentBase(document) + "SeleniumLog.html", "SeleniumLog", - "width=600,height=1000,bottom=0,right=0,status,scrollbars,resizable" - ); - this.logWindow.moveTo(window.screenX + 1210, window.screenY + window.outerHeight - 1400); - if (browserVersion.appearsToBeBrokenInitialIE6) { - // I would really prefer for the message to immediately appear in the log window, the instant the user requests that the log window be - // visible. But when I initially coded it this way, thou message simply didn't appear unless I stepped through the code with a debugger. - // So obviously there is some timing issue here which I don't have the patience to figure out. - var pendingMessage = new LogMessage("warn", "You appear to be running an unpatched IE 6, which is not stable and can crash due to memory problems. We recommend you run Windows update to install a more stable version of IE."); - this.pendingMessages.push(pendingMessage); - } - return this.logWindow; - }, - - show: function() { - if (! this.getLogWindow()) { - this.openLogWindow(); - } - setTimeout(function(){LOG.info("Log window displayed");}, 500); - }, - - logHook: function(className, message) { - }, - - log: function(className, message) { - var logWindow = this.getLogWindow(); - this.logHook(className, message); - if (logWindow) { - if (logWindow.append) { - if (this.pendingMessages.length > 0) { - logWindow.append("info: Appending missed logging messages", "info"); - while (this.pendingMessages.length > 0) { - var msg = this.pendingMessages.shift(); - logWindow.append(msg.type + ": " + msg.msg, msg.type); - } - logWindow.append("info: Done appending missed logging messages", "info"); - } - logWindow.append(className + ": " + message, className); - } - } else { - // uncomment this to turn on background logging - /* these logging messages are never flushed, which creates - an enormous array of strings that never stops growing. Only - turn this on if you need it for debugging! */ - //this.pendingMessages.push(new LogMessage(className, message)); - } - }, - - close: function(message) { - if (this.logWindow != null) { - try { - this.logWindow.close(); - } catch (e) { - // swallow exception - // the window is probably closed if we get an exception here - } - this.logWindow = null; - } - }, - - debug: function(message) { - this.log("debug", message); - }, - - info: function(message) { - this.log("info", message); - }, - - warn: function(message) { - this.log("warn", message); - }, - - error: function(message) { - this.log("error", message); - }, - - exception: function(exception) { - this.error("Unexpected Exception: " + extractExceptionMessage(exception)); - this.error("Exception details: " + describe(exception, ', ')); - } - -}; - -var LOG = new Logger(); - -var LogMessage = function(type, msg) { - this.type = type; - this.msg = msg; -} diff --git a/tests/test_tools/selenium/core/scripts/selenium-seleneserunner.js b/tests/test_tools/selenium/core/scripts/selenium-seleneserunner.js deleted file mode 100644 index 99c7efbc..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-seleneserunner.js +++ /dev/null @@ -1,451 +0,0 @@ -/* -* Copyright 2005 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. -* -*/ - -passColor = "#cfffcf"; -failColor = "#ffcfcf"; -errorColor = "#ffffff"; -workingColor = "#DEE7EC"; -doneColor = "#FFFFCC"; - -slowMode = false; - -var injectedSessionId; -var cmd1 = document.createElement("div"); -var cmd2 = document.createElement("div"); -var cmd3 = document.createElement("div"); -var cmd4 = document.createElement("div"); - -var postResult = "START"; -var debugMode = false; -var relayToRC = null; -var proxyInjectionMode = false; -var uniqueId = 'sel_' + Math.round(100000 * Math.random()); - -var SeleneseRunnerOptions = Class.create(); -Object.extend(SeleneseRunnerOptions.prototype, URLConfiguration.prototype); -Object.extend(SeleneseRunnerOptions.prototype, { - initialize: function() { - this._acquireQueryString(); - }, - getDebugMode: function() { - return this._getQueryParameter("debugMode"); - }, - - getContinue: function() { - return this._getQueryParameter("continue"); - }, - - getBaseUrl: function() { - return this._getQueryParameter("baseUrl"); - }, - - getDriverHost: function() { - return this._getQueryParameter("driverhost"); - }, - - getDriverPort: function() { - return this._getQueryParameter("driverport"); - }, - - getSessionId: function() { - return this._getQueryParameter("sessionId"); - }, - - _acquireQueryString: function () { - if (this.queryString) return; - if (browserVersion.isHTA) { - var args = this._extractArgs(); - if (args.length < 2) return null; - this.queryString = args[1]; - } else if (proxyInjectionMode) { - this.queryString = selenium.browserbot.getCurrentWindow().location.search.substr(1); - } else { - this.queryString = top.location.search.substr(1); - } - } - -}); -var runOptions; - -function runSeleniumTest() { - runOptions = new SeleneseRunnerOptions(); - var testAppWindow; - - if (runOptions.isMultiWindowMode()) { - testAppWindow = openSeparateApplicationWindow('Blank.html'); - } else if ($('myiframe') != null) { - testAppWindow = $('myiframe').contentWindow; - } - else { - proxyInjectionMode = true; - testAppWindow = window; - } - selenium = Selenium.createForWindow(testAppWindow); - if (!debugMode) { - debugMode = runOptions.getDebugMode(); - } - if (proxyInjectionMode) { - LOG.log = logToRc; - selenium.browserbot._modifyWindow(testAppWindow); - } - else if (debugMode) { - LOG.logHook = logToRc; - } - window.selenium = selenium; - - commandFactory = new CommandHandlerFactory(); - commandFactory.registerAll(selenium); - - currentTest = new SeleneseRunner(commandFactory); - - if (document.getElementById("commandList") != null) { - document.getElementById("commandList").appendChild(cmd4); - document.getElementById("commandList").appendChild(cmd3); - document.getElementById("commandList").appendChild(cmd2); - document.getElementById("commandList").appendChild(cmd1); - } - - var doContinue = runOptions.getContinue(); - if (doContinue != null) postResult = "OK"; - - currentTest.start(); -} - -function buildBaseUrl() { - var baseUrl = runOptions.getBaseUrl(); - if (baseUrl != null) { - return baseUrl; - } - var s = window.location.href - var slashPairOffset = s.indexOf("//") + "//".length - var pathSlashOffset = s.substring(slashPairOffset).indexOf("/") - return s.substring(0, slashPairOffset + pathSlashOffset) + "/selenium-server/core/"; -} - -function logToRc(message, logLevel) { - if (logLevel == null) { - logLevel = "debug"; - } - if (debugMode) { - sendToRC("logLevel=" + logLevel + ":" + message.replace(/[\n\r\015]/g, " ") + "\n"); - } -} - -function isArray(x) { - return ((typeof x) == "object") && (x["length"] != null); -} - -function serializeString(name, s) { - return name + "=unescape(\"" + escape(s) + "\");"; -} - -function serializeObject(name, x) -{ - var s = ''; - - if (isArray(x)) - { - s = name + "=new Array(); "; - var len = x["length"]; - for (var j = 0; j < len; j++) - { - s += serializeString(name + "[" + j + "]", x[j]); - } - } - else if (typeof x == "string") - { - s = serializeString(name, x); - } - else - { - throw "unrecognized object not encoded: " + name + "(" + x + ")"; - } - return s; -} - -function relayBotToRC(s) { -} - -function setSeleniumWindowName(seleniumWindowName) { - selenium.browserbot.getCurrentWindow()['seleniumWindowName'] = seleniumWindowName; -} - -function slowClicked() { - slowMode = !slowMode; -} - -SeleneseRunner = Class.create(); -Object.extend(SeleneseRunner.prototype, new TestLoop()); -Object.extend(SeleneseRunner.prototype, { - initialize : function(commandFactory) { - this.commandFactory = commandFactory; - this.requiresCallBack = true; - this.commandNode = null; - this.xmlHttpForCommandsAndResults = null; - }, - - nextCommand : function() { - var urlParms = ""; - if (postResult == "START") { - urlParms += "seleniumStart=true"; - } - this.xmlHttpForCommandsAndResults = XmlHttp.create(); - sendToRC(postResult, urlParms, this._HandleHttpResponse.bind(this), this.xmlHttpForCommandsAndResults); - }, - - commandStarted : function(command) { - this.commandNode = document.createElement("div"); - var innerHTML = command.command + '('; - if (command.target != null && command.target != "") { - innerHTML += command.target; - if (command.value != null && command.value != "") { - innerHTML += ', ' + command.value; - } - } - innerHTML += ")"; - this.commandNode.innerHTML = innerHTML; - this.commandNode.style.backgroundColor = workingColor; - if (document.getElementById("commandList") != null) { - document.getElementById("commandList").removeChild(cmd1); - document.getElementById("commandList").removeChild(cmd2); - document.getElementById("commandList").removeChild(cmd3); - document.getElementById("commandList").removeChild(cmd4); - cmd4 = cmd3; - cmd3 = cmd2; - cmd2 = cmd1; - cmd1 = this.commandNode; - document.getElementById("commandList").appendChild(cmd4); - document.getElementById("commandList").appendChild(cmd3); - document.getElementById("commandList").appendChild(cmd2); - document.getElementById("commandList").appendChild(cmd1); - } - }, - - commandComplete : function(result) { - - if (result.failed) { - if (postResult == "CONTINUATION") { - currentTest.aborted = true; - } - postResult = result.failureMessage; - this.commandNode.title = result.failureMessage; - this.commandNode.style.backgroundColor = failColor; - } else if (result.passed) { - postResult = "OK"; - this.commandNode.style.backgroundColor = passColor; - } else { - if (result.result == null) { - postResult = "OK"; - } else { - postResult = "OK," + result.result; - } - this.commandNode.style.backgroundColor = doneColor; - } - }, - - commandError : function(message) { - postResult = "ERROR: " + message; - this.commandNode.style.backgroundColor = errorColor; - this.commandNode.title = message; - }, - - testComplete : function() { - window.status = "Selenium Tests Complete, for this Test" - // Continue checking for new results - this.continueTest(); - postResult = "START"; - }, - - _HandleHttpResponse : function() { - if (this.xmlHttpForCommandsAndResults.readyState == 4) { - if (this.xmlHttpForCommandsAndResults.status == 200) { - var command = this._extractCommand(this.xmlHttpForCommandsAndResults); - this.currentCommand = command; - this.continueTestAtCurrentCommand(); - } else { - var s = 'xmlHttp returned: ' + this.xmlHttpForCommandsAndResults.status + ": " + this.xmlHttpForCommandsAndResults.statusText; - LOG.error(s); - this.currentCommand = null; - setTimeout(this.continueTestAtCurrentCommand.bind(this), 2000); - } - - } - }, - - _extractCommand : function(xmlHttp) { - if (slowMode) { - this._delay(2000); - } - - var command; - try { - var re = new RegExp("^(.*?)\n((.|[\r\n])*)"); - if (re.exec(xmlHttp.responseText)) { - command = RegExp.$1; - var rest = RegExp.$2; - rest = rest.trim(); - if (rest) { - eval(rest); - } - } - else { - command = xmlHttp.responseText; - } - } catch (e) { - alert('could not get responseText: ' + e.message); - } - if (command.substr(0, '|testComplete'.length) == '|testComplete') { - return null; - } - - return this._createCommandFromRequest(command); - }, - - - _delay : function(millis) { - var startMillis = new Date(); - while (true) { - milli = new Date(); - if (milli - startMillis > millis) { - break; - } - } - }, - -// Parses a URI query string into a SeleniumCommand object - _createCommandFromRequest : function(commandRequest) { - //decodeURIComponent doesn't strip plus signs - var processed = commandRequest.replace(/\+/g, "%20"); - // strip trailing spaces - var processed = processed.replace(/\s+$/, ""); - var vars = processed.split("&"); - var cmdArgs = new Object(); - for (var i = 0; i < vars.length; i++) { - var pair = vars[i].split("="); - cmdArgs[pair[0]] = pair[1]; - } - var cmd = cmdArgs['cmd']; - var arg1 = cmdArgs['1']; - if (null == arg1) arg1 = ""; - arg1 = decodeURIComponent(arg1); - var arg2 = cmdArgs['2']; - if (null == arg2) arg2 = ""; - arg2 = decodeURIComponent(arg2); - if (cmd == null) { - throw new Error("Bad command request: " + commandRequest); - } - return new SeleniumCommand(cmd, arg1, arg2); - } - -}) - - -function sendToRC(dataToBePosted, urlParms, callback, xmlHttpObject, async) { - if (async == null) { - async = true; - } - if (xmlHttpObject == null) { - xmlHttpObject = XmlHttp.create(); - } - var url = buildBaseUrl() + "driver/?" - if (urlParms) { - url += urlParms; - } - url += "&localFrameAddress=" + (proxyInjectionMode ? makeAddressToAUTFrame() : "top"); - url += "&seleniumWindowName=" + getSeleniumWindowName(); - url += "&uniqueId=" + uniqueId; - - if (callback == null) { - callback = function() { - }; - } - url += buildDriverParams() + preventBrowserCaching(); - xmlHttpObject.open("POST", url, async); - xmlHttpObject.onreadystatechange = callback; - xmlHttpObject.send(dataToBePosted); - return null; -} - -function buildDriverParams() { - var params = ""; - - var host = runOptions.getDriverHost(); - var port = runOptions.getDriverPort(); - if (host != undefined && port != undefined) { - params = params + "&driverhost=" + host + "&driverport=" + port; - } - - var sessionId = runOptions.getSessionId(); - if (sessionId == undefined) { - sessionId = injectedSessionId; - } - if (sessionId != undefined) { - params = params + "&sessionId=" + sessionId; - } - return params; -} - -function preventBrowserCaching() { - var t = (new Date()).getTime(); - return "&counterToMakeURsUniqueAndSoStopPageCachingInTheBrowser=" + t; -} - -// Return the name of the current window in the selenium recordkeeping. -// -// In selenium, the additional widow has no name. -// -// Additional pop-ups are associated with names given by the argument to the routine waitForPopUp. -// -// I try to arrange for widows which are opened in such manner to track their own names using the top-level property -// seleniumWindowName, but it is possible that this property will not be available (if the widow has just reloaded -// itself). In this case, return "?". -// -function getSeleniumWindowName() { - var w = (proxyInjectionMode ? selenium.browserbot.getCurrentWindow() : window); - if (w.opener == null) { - return ""; - } - if (w["seleniumWindowName"] == null) { - return "?"; - } - return w["seleniumWindowName"]; -} - -// construct a JavaScript expression which leads to my frame (i.e., the frame containing the window -// in which this code is operating) -function makeAddressToAUTFrame(w, frameNavigationalJSexpression) -{ - if (w == null) - { - w = top; - frameNavigationalJSexpression = "top"; - } - - if (w == selenium.browserbot.getCurrentWindow()) - { - return frameNavigationalJSexpression; - } - for (var j = 0; j < w.frames.length; j++) - { - var t = makeAddressToAUTFrame(w.frames[j], frameNavigationalJSexpression + ".frames[" + j + "]"); - if (t != null) - { - return t; - } - } - return null; -} diff --git a/tests/test_tools/selenium/core/scripts/selenium-testrunner.js b/tests/test_tools/selenium/core/scripts/selenium-testrunner.js deleted file mode 100644 index fd7f2076..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-testrunner.js +++ /dev/null @@ -1,1281 +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. -* -*/ - -// An object representing the current test, used external -var currentTest = null; // TODO: get rid of this global, which mirrors the htmlTestRunner.currentTest -var selenium = null; - -var htmlTestRunner; -var HtmlTestRunner = classCreate(); -objectExtend(HtmlTestRunner.prototype, { - initialize: function() { - this.metrics = new Metrics(); - this.controlPanel = new HtmlTestRunnerControlPanel(); - this.testFailed = false; - this.currentTest = null; - this.runAllTests = false; - this.appWindow = null; - // we use a timeout here to make sure the LOG has loaded first, so we can see _every_ error - setTimeout(fnBind(function() { - this.loadSuiteFrame(); - }, this), 500); - }, - - getTestSuite: function() { - return suiteFrame.getCurrentTestSuite(); - }, - - markFailed: function() { - this.testFailed = true; - this.getTestSuite().markFailed(); - }, - - loadSuiteFrame: function() { - if (selenium == null) { - var appWindow = this._getApplicationWindow(); - try { appWindow.location; } - catch (e) { - // when reloading, we may be pointing at an old window (Perm Denied) - setTimeout(fnBind(function() { - this.loadSuiteFrame(); - }, this), 50); - return; - } - selenium = Selenium.createForWindow(appWindow); - this._registerCommandHandlers(); - } - this.controlPanel.setHighlightOption(); - var testSuiteName = this.controlPanel.getTestSuiteName(); - var self = this; - if (testSuiteName) { - suiteFrame.load(testSuiteName, function() {setTimeout(fnBind(self._onloadTestSuite, self), 50)} ); - selenium.browserbot.baseUrl = absolutify(testSuiteName, window.location.href); - } - // DGF or should we use the old default? - // selenium.browserbot.baseUrl = window.location.href; - if (this.controlPanel.getBaseUrl()) { - selenium.browserbot.baseUrl = this.controlPanel.getBaseUrl(); - } - }, - - _getApplicationWindow: function () { - if (this.controlPanel.isMultiWindowMode()) { - return this._getSeparateApplicationWindow(); - } - return $('myiframe').contentWindow; - }, - - _getSeparateApplicationWindow: function () { - if (this.appWindow == null) { - this.appWindow = openSeparateApplicationWindow('TestRunner-splash.html', this.controlPanel.isAutomatedRun()); - } - return this.appWindow; - }, - - _onloadTestSuite:function () { - if (! this.getTestSuite().isAvailable()) { - return; - } - if (this.controlPanel.isAutomatedRun()) { - this.startTestSuite(); - } else if (this.controlPanel.getAutoUrl()) { - //todo what is the autourl doing, left to check it out - addLoadListener(this._getApplicationWindow(), fnBind(this._startSingleTest, this)); - this._getApplicationWindow().src = this.controlPanel.getAutoUrl(); - } else { - this.getTestSuite().getSuiteRows()[0].loadTestCase(); - } - }, - - _startSingleTest:function () { - removeLoadListener(getApplicationWindow(), fnBind(this._startSingleTest, this)); - var singleTestName = this.controlPanel.getSingleTestName(); - testFrame.load(singleTestName, fnBind(this.startTest, this)); - }, - - _registerCommandHandlers: function () { - this.commandFactory = new CommandHandlerFactory(); - this.commandFactory.registerAll(selenium); - }, - - startTestSuite: function() { - this.controlPanel.reset(); - this.metrics.resetMetrics(); - this.getTestSuite().reset(); - this.runAllTests = true; - this.runNextTest(); - }, - - runNextTest: function () { - this.getTestSuite().updateSuiteWithResultOfPreviousTest(); - if (!this.runAllTests) { - return; - } - this.getTestSuite().runNextTestInSuite(); - }, - - startTest: function () { - this.controlPanel.reset(); - testFrame.scrollToTop(); - //todo: move testFailed and storedVars to TestCase - this.testFailed = false; - storedVars = new Object(); - this.currentTest = new HtmlRunnerTestLoop(testFrame.getCurrentTestCase(), this.metrics, this.commandFactory); - currentTest = this.currentTest; - this.currentTest.start(); - }, - - runSingleTest:function() { - this.runAllTests = false; - this.metrics.resetMetrics(); - this.startTest(); - } -}); - -var runInterval = 0; - -/** SeleniumFrame encapsulates an iframe element */ -var SeleniumFrame = classCreate(); -objectExtend(SeleniumFrame.prototype, { - - initialize : function(frame) { - this.frame = frame; - addLoadListener(this.frame, fnBind(this._handleLoad, this)); - }, - - getDocument : function() { - return this.frame.contentWindow.document; - }, - - _handleLoad: function() { - this._attachStylesheet(); - this._onLoad(); - if (this.loadCallback) { - this.loadCallback(); - this.loadCallback = null; - } - }, - - _attachStylesheet: function() { - var d = this.getDocument(); - var head = d.getElementsByTagName('head').item(0); - var styleLink = d.createElement("link"); - styleLink.rel = "stylesheet"; - styleLink.type = "text/css"; - if (browserVersion && browserVersion.isChrome) { - // DGF We have to play a clever trick to get the right absolute path. - // This trick works on most browsers, (not IE), but is only needed in - // chrome - var tempLink = window.document.createElement("link"); - tempLink.href = "selenium-test.css"; // this will become an absolute href - styleLink.href = tempLink.href; - } else { - // this works in every browser (except Firefox in chrome mode) - var styleSheetPath = window.location.pathname.replace(/[^\/\\]+$/, "selenium-test.css"); - if (browserVersion.isIE && window.location.protocol == "file:") { - styleSheetPath = "file://" + styleSheetPath; - } - styleLink.href = styleSheetPath; - } - head.appendChild(styleLink); - }, - - _onLoad: function() { - }, - - scrollToTop : function() { - this.frame.contentWindow.scrollTo(0, 0); - }, - - _setLocation: function(location) { - var isChrome = browserVersion.isChrome || false; - var isHTA = browserVersion.isHTA || false; - // DGF TODO multiWindow - location += "?thisIsChrome=" + isChrome + "&thisIsHTA=" + isHTA; - if (browserVersion.isSafari) { - // safari doesn't reload the page when the location equals to current location. - // hence, set the location to blank so that the page will reload automatically. - this.frame.src = "about:blank"; - this.frame.src = location; - } else { - this.frame.contentWindow.location.replace(location); - } - }, - - load: function(/* url, [callback] */) { - if (arguments.length > 1) { - this.loadCallback = arguments[1]; - - } - this._setLocation(arguments[0]); - } - -}); - -/** HtmlTestSuiteFrame - encapsulates the suite iframe element */ -var HtmlTestSuiteFrame = classCreate(); -objectExtend(HtmlTestSuiteFrame.prototype, SeleniumFrame.prototype); -objectExtend(HtmlTestSuiteFrame.prototype, { - - getCurrentTestSuite: function() { - if (!this.currentTestSuite) { - this.currentTestSuite = new HtmlTestSuite(this.getDocument()); - } - return this.currentTestSuite; - } - -}); - -/** HtmlTestFrame - encapsulates the test-case iframe element */ -var HtmlTestFrame = classCreate(); -objectExtend(HtmlTestFrame.prototype, SeleniumFrame.prototype); -objectExtend(HtmlTestFrame.prototype, { - - _onLoad: function() { - this.currentTestCase = new HtmlTestCase(this.getDocument(), htmlTestRunner.getTestSuite().getCurrentRow()); - }, - - getCurrentTestCase: function() { - return this.currentTestCase; - } - -}); - -function onSeleniumLoad() { - suiteFrame = new HtmlTestSuiteFrame(getSuiteFrame()); - testFrame = new HtmlTestFrame(getTestFrame()); - htmlTestRunner = new HtmlTestRunner(); -} - -var suiteFrame; -var testFrame; - -function getSuiteFrame() { - var f = $('testSuiteFrame'); - if (f == null) { - f = top; - // proxyInjection mode does not set myiframe - } - return f; -} - -function getTestFrame() { - var f = $('testFrame'); - if (f == null) { - f = top; - // proxyInjection mode does not set myiframe - } - return f; -} - -var HtmlTestRunnerControlPanel = classCreate(); -objectExtend(HtmlTestRunnerControlPanel.prototype, URLConfiguration.prototype); -objectExtend(HtmlTestRunnerControlPanel.prototype, { - initialize: function() { - this._acquireQueryString(); - - this.runInterval = 0; - - this.highlightOption = $('highlightOption'); - this.pauseButton = $('pauseTest'); - this.stepButton = $('stepTest'); - - this.highlightOption.onclick = fnBindAsEventListener((function() { - this.setHighlightOption(); - }), this); - this.pauseButton.onclick = fnBindAsEventListener(this.pauseCurrentTest, this); - this.stepButton.onclick = fnBindAsEventListener(this.stepCurrentTest, this); - - - this.speedController = new Control.Slider('speedHandle', 'speedTrack', { - range: $R(0, 1000), - onSlide: fnBindAsEventListener(this.setRunInterval, this), - onChange: fnBindAsEventListener(this.setRunInterval, this) - }); - - this._parseQueryParameter(); - }, - - setHighlightOption: function () { - var isHighlight = this.highlightOption.checked; - selenium.browserbot.setShouldHighlightElement(isHighlight); - }, - - _parseQueryParameter: function() { - var tempRunInterval = this._getQueryParameter("runInterval"); - if (tempRunInterval) { - this.setRunInterval(tempRunInterval); - } - this.highlightOption.checked = this._getQueryParameter("highlight"); - }, - - setRunInterval: function(runInterval) { - this.runInterval = runInterval; - }, - - setToPauseAtNextCommand: function() { - this.runInterval = -1; - }, - - pauseCurrentTest: function () { - this.setToPauseAtNextCommand(); - this._switchPauseButtonToContinue(); - }, - - continueCurrentTest: function () { - this.reset(); - currentTest.resume(); - }, - - reset: function() { - // this.runInterval = this.speedController.value; - this._switchContinueButtonToPause(); - }, - - _switchContinueButtonToPause: function() { - this.pauseButton.className = "cssPauseTest"; - this.pauseButton.onclick = fnBindAsEventListener(this.pauseCurrentTest, this); - }, - - _switchPauseButtonToContinue: function() { - $('stepTest').disabled = false; - this.pauseButton.className = "cssContinueTest"; - this.pauseButton.onclick = fnBindAsEventListener(this.continueCurrentTest, this); - }, - - stepCurrentTest: function () { - this.setToPauseAtNextCommand(); - currentTest.resume(); - }, - - isAutomatedRun: function() { - return this._isQueryParameterTrue("auto"); - }, - - shouldSaveResultsToFile: function() { - return this._isQueryParameterTrue("save"); - }, - - closeAfterTests: function() { - return this._isQueryParameterTrue("close"); - }, - - getTestSuiteName: function() { - return this._getQueryParameter("test"); - }, - - getSingleTestName: function() { - return this._getQueryParameter("singletest"); - }, - - getAutoUrl: function() { - return this._getQueryParameter("autoURL"); - }, - - getResultsUrl: function() { - return this._getQueryParameter("resultsUrl"); - }, - - _acquireQueryString: function() { - if (this.queryString) return; - if (browserVersion.isHTA) { - var args = this._extractArgs(); - if (args.length < 2) return null; - this.queryString = args[1]; - } else { - this.queryString = location.search.substr(1); - } - } - -}); - -var AbstractResultAwareRow = classCreate(); -objectExtend(AbstractResultAwareRow.prototype, { - - initialize: function(trElement) { - this.trElement = trElement; - }, - - setStatus: function(status) { - this.unselect(); - this.trElement.className = this.trElement.className.replace(/status_[a-z]+/, ""); - if (status) { - addClassName(this.trElement, "status_" + status); - } - }, - - select: function() { - addClassName(this.trElement, "selected"); - safeScrollIntoView(this.trElement); - }, - - unselect: function() { - removeClassName(this.trElement, "selected"); - }, - - markPassed: function() { - this.setStatus("passed"); - }, - - markDone: function() { - this.setStatus("done"); - }, - - markFailed: function() { - this.setStatus("failed"); - } - -}); - -var TitleRow = classCreate(); -objectExtend(TitleRow.prototype, AbstractResultAwareRow.prototype); -objectExtend(TitleRow.prototype, { - - initialize: function(trElement) { - this.trElement = trElement; - trElement.className = "title"; - } - -}); - -var HtmlTestCaseRow = classCreate(); -objectExtend(HtmlTestCaseRow.prototype, AbstractResultAwareRow.prototype); -objectExtend(HtmlTestCaseRow.prototype, { - - getCommand: function () { - return new SeleniumCommand(getText(this.trElement.cells[0]), - getText(this.trElement.cells[1]), - getText(this.trElement.cells[2]), - this.isBreakpoint()); - }, - - markFailed: function(errorMsg) { - AbstractResultAwareRow.prototype.markFailed.call(this, errorMsg); - this.setMessage(errorMsg); - }, - - setMessage: function(message) { - setText(this.trElement.cells[2], message); - }, - - reset: function() { - this.setStatus(null); - var thirdCell = this.trElement.cells[2]; - if (thirdCell) { - if (thirdCell.originalHTML) { - thirdCell.innerHTML = thirdCell.originalHTML; - } else { - thirdCell.originalHTML = thirdCell.innerHTML; - } - } - }, - - onClick: function() { - if (this.trElement.isBreakpoint == undefined) { - this.trElement.isBreakpoint = true; - addClassName(this.trElement, "breakpoint"); - } else { - this.trElement.isBreakpoint = undefined; - removeClassName(this.trElement, "breakpoint"); - } - }, - - addBreakpointSupport: function() { - elementSetStyle(this.trElement, {"cursor" : "pointer"}); - this.trElement.onclick = fnBindAsEventListener(function() { - this.onClick(); - }, this); - }, - - isBreakpoint: function() { - if (this.trElement.isBreakpoint == undefined || this.trElement.isBreakpoint == null) { - return false - } - return this.trElement.isBreakpoint; - } -}); - -var HtmlTestSuiteRow = classCreate(); -objectExtend(HtmlTestSuiteRow.prototype, AbstractResultAwareRow.prototype); -objectExtend(HtmlTestSuiteRow.prototype, { - - initialize: function(trElement, testFrame, htmlTestSuite) { - this.trElement = trElement; - this.testFrame = testFrame; - this.htmlTestSuite = htmlTestSuite; - this.link = trElement.getElementsByTagName("a")[0]; - this.link.onclick = fnBindAsEventListener(this._onClick, this); - }, - - reset: function() { - this.setStatus(null); - }, - - _onClick: function() { - this.loadTestCase(null); - return false; - }, - - loadTestCase: function(onloadFunction) { - this.htmlTestSuite.unselectCurrentRow(); - this.select(); - this.htmlTestSuite.currentRowInSuite = this.trElement.rowIndex - 1; - // If the row has a stored results table, use that - var resultsFromPreviousRun = this.trElement.cells[1]; - if (resultsFromPreviousRun) { - // todo: delegate to TestFrame, e.g. - // this.testFrame.restoreTestCase(resultsFromPreviousRun.innerHTML); - var testBody = this.testFrame.getDocument().body; - testBody.innerHTML = resultsFromPreviousRun.innerHTML; - this.testFrame._onLoad(); - if (onloadFunction) { - onloadFunction(); - } - } else { - this.testFrame.load(this.link.href, onloadFunction); - } - }, - - saveTestResults: function() { - // todo: GLOBAL ACCESS! - var resultHTML = this.testFrame.getDocument().body.innerHTML; - if (!resultHTML) return; - - // todo: why create this div? - var divElement = this.trElement.ownerDocument.createElement("div"); - divElement.innerHTML = resultHTML; - - var hiddenCell = this.trElement.ownerDocument.createElement("td"); - hiddenCell.appendChild(divElement); - hiddenCell.style.display = "none"; - - this.trElement.appendChild(hiddenCell); - } - -}); - -var HtmlTestSuite = classCreate(); -objectExtend(HtmlTestSuite.prototype, { - - initialize: function(suiteDocument) { - this.suiteDocument = suiteDocument; - this.suiteRows = this._collectSuiteRows(); - this.titleRow = new TitleRow(this.getTestTable().rows[0]); - this.reset(); - }, - - reset: function() { - this.failed = false; - this.currentRowInSuite = -1; - this.titleRow.setStatus(null); - for (var i = 0; i < this.suiteRows.length; i++) { - var row = this.suiteRows[i]; - row.reset(); - } - }, - - getSuiteRows: function() { - return this.suiteRows; - }, - - getTestTable: function() { - var tables = $A(this.suiteDocument.getElementsByTagName("table")); - return tables[0]; - }, - - isAvailable: function() { - return this.getTestTable() != null; - }, - - _collectSuiteRows: function () { - var result = []; - var tables = $A(this.suiteDocument.getElementsByTagName("table")); - var testTable = tables[0]; - for (rowNum = 1; rowNum < testTable.rows.length; rowNum++) { - var rowElement = testTable.rows[rowNum]; - result.push(new HtmlTestSuiteRow(rowElement, testFrame, this)); - } - - // process the unsuited rows as well - for (var tableNum = 1; tableNum < $A(this.suiteDocument.getElementsByTagName("table")).length; tableNum++) { - testTable = tables[tableNum]; - for (rowNum = 1; rowNum < testTable.rows.length; rowNum++) { - var rowElement = testTable.rows[rowNum]; - new HtmlTestSuiteRow(rowElement, testFrame, this); - } - } - return result; - }, - - getCurrentRow: function() { - if (this.currentRowInSuite == -1) { - return null; - } - return this.suiteRows[this.currentRowInSuite]; - }, - - unselectCurrentRow: function() { - var currentRow = this.getCurrentRow() - if (currentRow) { - currentRow.unselect(); - } - }, - - markFailed: function() { - this.failed = true; - this.titleRow.markFailed(); - }, - - markDone: function() { - if (!this.failed) { - this.titleRow.markPassed(); - } - }, - - _startCurrentTestCase: function() { - this.getCurrentRow().loadTestCase(fnBind(htmlTestRunner.startTest, htmlTestRunner)); - }, - - _onTestSuiteComplete: function() { - this.markDone(); - new TestResult(this.failed, this.getTestTable()).post(); - }, - - updateSuiteWithResultOfPreviousTest: function() { - if (this.currentRowInSuite >= 0) { - this.getCurrentRow().saveTestResults(); - } - }, - - runNextTestInSuite: function() { - this.currentRowInSuite++; - - // If we are done with all of the tests, set the title bar as pass or fail - if (this.currentRowInSuite >= this.suiteRows.length) { - this._onTestSuiteComplete(); - } else { - this._startCurrentTestCase(); - } - } - - - -}); - -var TestResult = classCreate(); -objectExtend(TestResult.prototype, { - -// Post the results to a servlet, CGI-script, etc. The URL of the -// results-handler defaults to "/postResults", but an alternative location -// can be specified by providing a "resultsUrl" query parameter. -// -// Parameters passed to the results-handler are: -// result: passed/failed depending on whether the suite passed or failed -// totalTime: the total running time in seconds for the suite. -// -// numTestPasses: the total number of tests which passed. -// numTestFailures: the total number of tests which failed. -// -// numCommandPasses: the total number of commands which passed. -// numCommandFailures: the total number of commands which failed. -// numCommandErrors: the total number of commands which errored. -// -// suite: the suite table, including the hidden column of test results -// testTable.1 to testTable.N: the individual test tables -// - initialize: function (suiteFailed, suiteTable) { - this.controlPanel = htmlTestRunner.controlPanel; - this.metrics = htmlTestRunner.metrics; - this.suiteFailed = suiteFailed; - this.suiteTable = suiteTable; - }, - - post: function () { - if (!this.controlPanel.isAutomatedRun()) { - return; - } - var form = document.createElement("form"); - document.body.appendChild(form); - - form.id = "resultsForm"; - form.method = "post"; - form.target = "myiframe"; - - var resultsUrl = this.controlPanel.getResultsUrl(); - if (!resultsUrl) { - resultsUrl = "./postResults"; - } - - var actionAndParameters = resultsUrl.split('?', 2); - form.action = actionAndParameters[0]; - var resultsUrlQueryString = actionAndParameters[1]; - - form.createHiddenField = function(name, value) { - input = document.createElement("input"); - input.type = "hidden"; - input.name = name; - input.value = value; - this.appendChild(input); - }; - - if (resultsUrlQueryString) { - var clauses = resultsUrlQueryString.split('&'); - for (var i = 0; i < clauses.length; i++) { - var keyValuePair = clauses[i].split('=', 2); - var key = unescape(keyValuePair[0]); - var value = unescape(keyValuePair[1]); - form.createHiddenField(key, value); - } - } - - form.createHiddenField("selenium.version", Selenium.version); - form.createHiddenField("selenium.revision", Selenium.revision); - - form.createHiddenField("result", this.suiteFailed ? "failed" : "passed"); - - form.createHiddenField("totalTime", Math.floor((this.metrics.currentTime - this.metrics.startTime) / 1000)); - form.createHiddenField("numTestPasses", this.metrics.numTestPasses); - form.createHiddenField("numTestFailures", this.metrics.numTestFailures); - form.createHiddenField("numCommandPasses", this.metrics.numCommandPasses); - form.createHiddenField("numCommandFailures", this.metrics.numCommandFailures); - form.createHiddenField("numCommandErrors", this.metrics.numCommandErrors); - - // Create an input for each test table. The inputs are named - // testTable.1, testTable.2, etc. - for (rowNum = 1; rowNum < this.suiteTable.rows.length; rowNum++) { - // If there is a second column, then add a new input - if (this.suiteTable.rows[rowNum].cells.length > 1) { - var resultCell = this.suiteTable.rows[rowNum].cells[1]; - form.createHiddenField("testTable." + rowNum, resultCell.innerHTML); - // remove the resultCell, so it's not included in the suite HTML - resultCell.parentNode.removeChild(resultCell); - } - } - - form.createHiddenField("numTestTotal", rowNum); - - // Add HTML for the suite itself - form.createHiddenField("suite", this.suiteTable.parentNode.innerHTML); - - if (this.controlPanel.shouldSaveResultsToFile()) { - this._saveToFile(resultsUrl, form); - } else { - form.submit(); - } - document.body.removeChild(form); - if (this.controlPanel.closeAfterTests()) { - window.top.close(); - } - }, - - _saveToFile: function (fileName, form) { - // This only works when run as an IE HTA - var inputs = new Object(); - for (var i = 0; i < form.elements.length; i++) { - inputs[form.elements[i].name] = form.elements[i].value; - } - var objFSO = new ActiveXObject("Scripting.FileSystemObject") - var scriptFile = objFSO.CreateTextFile(fileName); - scriptFile.WriteLine("<html><body>\n<h1>Test suite results </h1>" + - "\n\n<table>\n<tr>\n<td>result:</td>\n<td>" + inputs["result"] + "</td>\n" + - "</tr>\n<tr>\n<td>totalTime:</td>\n<td>" + inputs["totalTime"] + "</td>\n</tr>\n" + - "<tr>\n<td>numTestPasses:</td>\n<td>" + inputs["numTestPasses"] + "</td>\n</tr>\n" + - "<tr>\n<td>numTestFailures:</td>\n<td>" + inputs["numTestFailures"] + "</td>\n</tr>\n" + - "<tr>\n<td>numCommandPasses:</td>\n<td>" + inputs["numCommandPasses"] + "</td>\n</tr>\n" + - "<tr>\n<td>numCommandFailures:</td>\n<td>" + inputs["numCommandFailures"] + "</td>\n</tr>\n" + - "<tr>\n<td>numCommandErrors:</td>\n<td>" + inputs["numCommandErrors"] + "</td>\n</tr>\n" + - "<tr>\n<td>" + inputs["suite"] + "</td>\n<td> </td>\n</tr>"); - var testNum = inputs["numTestTotal"]; - for (var rowNum = 1; rowNum < testNum; rowNum++) { - scriptFile.WriteLine("<tr>\n<td>" + inputs["testTable." + rowNum] + "</td>\n<td> </td>\n</tr>"); - } - scriptFile.WriteLine("</table></body></html>"); - scriptFile.Close(); - } -}); - -/** HtmlTestCase encapsulates an HTML test document */ -var HtmlTestCase = classCreate(); -objectExtend(HtmlTestCase.prototype, { - - initialize: function(testDocument, htmlTestSuiteRow) { - if (testDocument == null) { - throw "testDocument should not be null"; - } - if (htmlTestSuiteRow == null) { - throw "htmlTestSuiteRow should not be null"; - } - this.testDocument = testDocument; - this.htmlTestSuiteRow = htmlTestSuiteRow; - this.headerRow = new TitleRow(this.testDocument.getElementsByTagName("tr")[0]); - this.commandRows = this._collectCommandRows(); - this.nextCommandRowIndex = 0; - this._addBreakpointSupport(); - }, - - _collectCommandRows: function () { - var commandRows = []; - var tables = $A(this.testDocument.getElementsByTagName("table")); - var self = this; - for (var i = 0; i < tables.length; i++) { - var table = tables[i]; - var tableRows = $A(table.rows); - for (var j = 0; j < tableRows.length; j++) { - var candidateRow = tableRows[j]; - if (self.isCommandRow(candidateRow)) { - commandRows.push(new HtmlTestCaseRow(candidateRow)); - } - } - } - return commandRows; - }, - - isCommandRow: function (row) { - return row.cells.length >= 3; - }, - - reset: function() { - /** - * reset the test to runnable state - */ - this.nextCommandRowIndex = 0; - - this.setStatus(''); - for (var i = 0; i < this.commandRows.length; i++) { - var row = this.commandRows[i]; - row.reset(); - } - - // remove any additional fake "error" row added to the end of the document - var errorElement = this.testDocument.getElementById('error'); - if (errorElement) { - errorElement.parentNode.removeChild(errorElement); - } - }, - - getCommandRows: function () { - return this.commandRows; - }, - - setStatus: function(status) { - this.headerRow.setStatus(status); - }, - - markFailed: function() { - this.setStatus("failed"); - this.htmlTestSuiteRow.markFailed(); - }, - - markPassed: function() { - this.setStatus("passed"); - this.htmlTestSuiteRow.markPassed(); - }, - - addErrorMessage: function(errorMsg, currentRow) { - errorMsg = errorMsg.replace(/ /g, String.fromCharCode(160)).replace("\n", '\\n'); - if (currentRow) { - currentRow.markFailed(errorMsg); - } else { - var errorElement = this.testDocument.createElement("p"); - errorElement.id = "error"; - setText(errorElement, errorMsg); - this.testDocument.body.appendChild(errorElement); - errorElement.className = "status_failed"; - } - }, - - _addBreakpointSupport: function() { - for (var i = 0; i < this.commandRows.length; i++) { - var row = this.commandRows[i]; - row.addBreakpointSupport(); - } - }, - - hasMoreCommandRows: function() { - return this.nextCommandRowIndex < this.commandRows.length; - }, - - getNextCommandRow: function() { - if (this.hasMoreCommandRows()) { - return this.commandRows[this.nextCommandRowIndex++]; - } - return null; - } - -}); - - -// TODO: split out an JavascriptTestCase class to handle the "sejs" stuff - -var get_new_rows = function() { - var row_array = new Array(); - for (var i = 0; i < new_block.length; i++) { - - var new_source = (new_block[i][0].tokenizer.source.slice(new_block[i][0].start, - new_block[i][0].end)); - - var row = '<td style="display:none;" class="js">getEval</td>' + - '<td style="display:none;">currentTest.doNextCommand()</td>' + - '<td style="white-space: pre;">' + new_source + '</td>' + - '<td></td>' - - row_array.push(row); - } - return row_array; -}; - - -var Metrics = classCreate(); -objectExtend(Metrics.prototype, { - initialize: function() { - // The number of tests run - this.numTestPasses = 0; - // The number of tests that have failed - this.numTestFailures = 0; - // The number of commands which have passed - this.numCommandPasses = 0; - // The number of commands which have failed - this.numCommandFailures = 0; - // The number of commands which have caused errors (element not found) - this.numCommandErrors = 0; - // The time that the test was started. - this.startTime = null; - // The current time. - this.currentTime = null; - }, - - printMetrics: function() { - setText($('commandPasses'), this.numCommandPasses); - setText($('commandFailures'), this.numCommandFailures); - setText($('commandErrors'), this.numCommandErrors); - setText($('testRuns'), this.numTestPasses + this.numTestFailures); - setText($('testFailures'), this.numTestFailures); - - this.currentTime = new Date().getTime(); - - var timeDiff = this.currentTime - this.startTime; - var totalSecs = Math.floor(timeDiff / 1000); - - var minutes = Math.floor(totalSecs / 60); - var seconds = totalSecs % 60; - - setText($('elapsedTime'), this._pad(minutes) + ":" + this._pad(seconds)); - }, - -// Puts a leading 0 on num if it is less than 10 - _pad: function(num) { - return (num > 9) ? num : "0" + num; - }, - - resetMetrics: function() { - this.numTestPasses = 0; - this.numTestFailures = 0; - this.numCommandPasses = 0; - this.numCommandFailures = 0; - this.numCommandErrors = 0; - this.startTime = new Date().getTime(); - } - -}); - -var HtmlRunnerCommandFactory = classCreate(); -objectExtend(HtmlRunnerCommandFactory.prototype, { - - initialize: function(seleniumCommandFactory, testLoop) { - this.seleniumCommandFactory = seleniumCommandFactory; - this.testLoop = testLoop; - this.handlers = {}; - //todo: register commands - }, - - getCommandHandler: function(command) { - if (this.handlers[command]) { - return this.handlers[command]; - } - return this.seleniumCommandFactory.getCommandHandler(command); - } - -}); - -var HtmlRunnerTestLoop = classCreate(); -objectExtend(HtmlRunnerTestLoop.prototype, new TestLoop()); -objectExtend(HtmlRunnerTestLoop.prototype, { - initialize: function(htmlTestCase, metrics, seleniumCommandFactory) { - - this.commandFactory = new HtmlRunnerCommandFactory(seleniumCommandFactory, this); - this.metrics = metrics; - - this.htmlTestCase = htmlTestCase; - - se = selenium; - global.se = selenium; - - this.currentRow = null; - this.currentRowIndex = 0; - - // used for selenium tests in javascript - this.currentItem = null; - this.commandAgenda = new Array(); - this.expectedFailure = null; - this.expectedFailureType = null; - - this.htmlTestCase.reset(); - - this.sejsElement = this.htmlTestCase.testDocument.getElementById('sejs'); - if (this.sejsElement) { - var fname = 'Selenium JavaScript'; - parse_result = parse(this.sejsElement.innerHTML, fname, 0); - - var x2 = new ExecutionContext(GLOBAL_CODE); - ExecutionContext.current = x2; - - execute(parse_result, x2) - } - }, - - _advanceToNextRow: function() { - if (this.htmlTestCase.hasMoreCommandRows()) { - this.currentRow = this.htmlTestCase.getNextCommandRow(); - if (this.sejsElement) { - this.currentItem = agenda.pop(); - this.currentRowIndex++; - } - } else { - this.currentRow = null; - this.currentItem = null; - } - }, - - nextCommand : function() { - this._advanceToNextRow(); - if (this.currentRow == null) { - return null; - } - return this.currentRow.getCommand(); - }, - - commandStarted : function() { - $('pauseTest').disabled = false; - this.currentRow.select(); - this.metrics.printMetrics(); - }, - - commandComplete : function(result) { - this._checkExpectedFailure(result); - if (result.failed) { - this.metrics.numCommandFailures += 1; - this._recordFailure(result.failureMessage); - } else if (result.passed) { - this.metrics.numCommandPasses += 1; - this.currentRow.markPassed(); - } else { - this.currentRow.markDone(); - } - }, - - _checkExpectedFailure : function(result) { - if (this.expectedFailure != null) { - if (this.expectedFailureJustSet) { - this.expectedFailureJustSet = false; - return; - } - if (!result.failed) { - result.passed = false; - result.failed = true; - result.failureMessage = "Expected " + this.expectedFailureType + " did not occur."; - } else { - if (PatternMatcher.matches(this.expectedFailure, result.failureMessage)) { - var failureType = result.error ? "error" : "failure"; - if (failureType == this.expectedFailureType) { - result.failed = false; - result.passed = true; - } else { - result.failed = true; - result.failureMessage = "Expected "+this.expectedFailureType+", but "+failureType+" occurred instead"; - } - } else { - result.failed = true; - result.failureMessage = "Expected " + this.expectedFailureType + " message '" + this.expectedFailure - + "' but was '" + result.failureMessage + "'"; - } - } - this.expectedFailure = null; - this.expectedFailureType = null; - } - }, - - commandError : function(errorMessage) { - var tempResult = {}; - tempResult.passed = false; - tempResult.failed = true; - tempResult.error = true; - tempResult.failureMessage = errorMessage; - this._checkExpectedFailure(tempResult); - if (tempResult.passed) { - this.currentRow.markDone(); - return true; - } - errorMessage = tempResult.failureMessage; - this.metrics.numCommandErrors += 1; - this._recordFailure(errorMessage); - }, - - _recordFailure : function(errorMsg) { - LOG.warn("currentTest.recordFailure: " + errorMsg); - htmlTestRunner.markFailed(); - this.htmlTestCase.addErrorMessage(errorMsg, this.currentRow); - }, - - testComplete : function() { - $('pauseTest').disabled = true; - $('stepTest').disabled = true; - if (htmlTestRunner.testFailed) { - this.htmlTestCase.markFailed(); - this.metrics.numTestFailures += 1; - } else { - this.htmlTestCase.markPassed(); - this.metrics.numTestPasses += 1; - } - - this.metrics.printMetrics(); - - window.setTimeout(function() { - htmlTestRunner.runNextTest(); - }, 1); - }, - - getCommandInterval : function() { - return htmlTestRunner.controlPanel.runInterval; - }, - - pause : function() { - htmlTestRunner.controlPanel.pauseCurrentTest(); - }, - - doNextCommand: function() { - var _n = this.currentItem[0]; - var _x = this.currentItem[1]; - - new_block = new Array() - execute(_n, _x); - if (new_block.length > 0) { - var the_table = this.htmlTestCase.testDocument.getElementById("se-js-table") - var loc = this.currentRowIndex - var new_rows = get_new_rows() - - // make the new statements visible on screen... - for (var i = 0; i < new_rows.length; i++) { - the_table.insertRow(loc + 1); - the_table.rows[loc + 1].innerHTML = new_rows[i]; - this.commandRows.unshift(the_table.rows[loc + 1]) - } - - } - } - -}); - -Selenium.prototype.doPause = function(waitTime) { - /** Wait for the specified amount of time (in milliseconds) - * @param waitTime the amount of time to sleep (in milliseconds) - */ - // todo: should not refer to currentTest directly - currentTest.pauseInterval = waitTime; -}; - -Selenium.prototype.doBreak = function() { - /** Halt the currently running test, and wait for the user to press the Continue button. - * This command is useful for debugging, but be careful when using it, because it will - * force automated tests to hang until a user intervenes manually. - */ - // todo: should not refer to controlPanel directly - htmlTestRunner.controlPanel.setToPauseAtNextCommand(); -}; - -Selenium.prototype.doStore = function(expression, variableName) { - /** This command is a synonym for storeExpression. - * @param expression the value to store - * @param variableName the name of a <a href="#storedVars">variable</a> in which the result is to be stored. - */ - storedVars[variableName] = expression; -} - -/* - * Click on the located element, and attach a callback to notify - * when the page is reloaded. - */ -// DGF TODO this code has been broken for some time... what is it trying to accomplish? -Selenium.prototype.XXXdoModalDialogTest = function(returnValue) { - this.browserbot.doModalDialogTest(returnValue); -}; - -Selenium.prototype.doEcho = function(message) { - /** Prints the specified message into the third table cell in your Selenese tables. - * Useful for debugging. - * @param message the message to print - */ - currentTest.currentRow.setMessage(message); -} - -Selenium.prototype.assertSelected = function(selectLocator, optionLocator) { - /** - * Verifies that the selected option of a drop-down satisfies the optionSpecifier. <i>Note that this command is deprecated; you should use assertSelectedLabel, assertSelectedValue, assertSelectedIndex, or assertSelectedId instead.</i> - * - * <p>See the select command for more information about option locators.</p> - * - * @param selectLocator an <a href="#locators">element locator</a> identifying a drop-down menu - * @param optionLocator an option locator, typically just an option label (e.g. "John Smith") - */ - var element = this.page().findElement(selectLocator); - var locator = this.optionLocatorFactory.fromLocatorString(optionLocator); - if (element.selectedIndex == -1) - { - Assert.fail("No option selected"); - } - locator.assertSelected(element); -}; - -Selenium.prototype.assertFailureOnNext = function(message) { - /** - * Tell Selenium to expect a failure on the next command execution. - * @param message The failure message we should expect. This command will fail if the wrong failure message appears. - */ - if (!message) { - throw new SeleniumError("Message must be provided"); - } - - currentTest.expectedFailure = message; - currentTest.expectedFailureType = "failure"; - currentTest.expectedFailureJustSet = true; -}; - -Selenium.prototype.assertErrorOnNext = function(message) { - /** - * Tell Selenium to expect an error on the next command execution. - * @param message The error message we should expect. This command will fail if the wrong error message appears. - */ - // This command temporarily installs a CommandFactory that generates - // CommandHandlers that expect an error. - if (!message) { - throw new SeleniumError("Message must be provided"); - } - - currentTest.expectedFailure = message; - currentTest.expectedFailureType = "error"; - currentTest.expectedFailureJustSet = true; -}; - diff --git a/tests/test_tools/selenium/core/scripts/selenium-version.js b/tests/test_tools/selenium/core/scripts/selenium-version.js deleted file mode 100644 index 4156723d..00000000 --- a/tests/test_tools/selenium/core/scripts/selenium-version.js +++ /dev/null @@ -1,5 +0,0 @@ -Selenium.version = "0.8.2"; -Selenium.revision = "1727"; - -window.top.document.title += " v" + Selenium.version + " [" + Selenium.revision + "]"; - diff --git a/tests/test_tools/selenium/core/scripts/user-extensions.js.sample b/tests/test_tools/selenium/core/scripts/user-extensions.js.sample deleted file mode 100644 index 0f0ca840..00000000 --- a/tests/test_tools/selenium/core/scripts/user-extensions.js.sample +++ /dev/null @@ -1,75 +0,0 @@ -/* - * By default, Selenium looks for a file called "user-extensions.js", and loads and javascript - * code found in that file. This file is a sample of what that file could look like. - * - * user-extensions.js provides a convenient location for adding extensions to Selenium, like - * new actions, checks and locator-strategies. - * By default, this file does not exist. Users can create this file and place their extension code - * in this common location, removing the need to modify the Selenium sources, and hopefully assisting - * with the upgrade process. - * - * You can find contributed extensions at http://wiki.openqa.org/display/SEL/Contributed%20User-Extensions - */ - -// The following examples try to give an indication of how Selenium can be extended with javascript. - -// All do* methods on the Selenium prototype are added as actions. -// Eg add a typeRepeated action to Selenium, which types the text twice into a text box. -// The typeTwiceAndWait command will be available automatically -Selenium.prototype.doTypeRepeated = function(locator, text) { - // All locator-strategies are automatically handled by "findElement" - var element = this.page().findElement(locator); - - // Create the text to type - var valueToType = text + text; - - // Replace the element text with the new text - this.page().replaceText(element, valueToType); -}; - -// All assert* methods on the Selenium prototype are added as checks. -// Eg add a assertValueRepeated check, that makes sure that the element value -// consists of the supplied text repeated. -// The verify version will be available automatically. -Selenium.prototype.assertValueRepeated = function(locator, text) { - // All locator-strategies are automatically handled by "findElement" - var element = this.page().findElement(locator); - - // Create the text to verify - var expectedValue = text + text; - - // Get the actual element value - var actualValue = element.value; - - // Make sure the actual value matches the expected - Assert.matches(expectedValue, actualValue); -}; - -// All get* methods on the Selenium prototype result in -// store, assert, assertNot, verify, verifyNot, waitFor, and waitForNot commands. -// E.g. add a getTextLength method that returns the length of the text -// of a specified element. -// Will result in support for storeTextLength, assertTextLength, etc. -Selenium.prototype.getTextLength = function(locator) { - return this.getText(locator).length; -}; - -// All locateElementBy* methods are added as locator-strategies. -// Eg add a "valuerepeated=" locator, that finds the first element with the supplied value, repeated. -// The "inDocument" is a the document you are searching. -PageBot.prototype.locateElementByValueRepeated = function(text, inDocument) { - // Create the text to search for - var expectedValue = text + text; - - // Loop through all elements, looking for ones that have a value === our expected value - var allElements = inDocument.getElementsByTagName("*"); - for (var i = 0; i < allElements.length; i++) { - var testElement = allElements[i]; - if (testElement.value && testElement.value === expectedValue) { - return testElement; - } - } - return null; -}; - - diff --git a/tests/test_tools/selenium/core/scripts/xmlextras.js b/tests/test_tools/selenium/core/scripts/xmlextras.js deleted file mode 100644 index 267aa058..00000000 --- a/tests/test_tools/selenium/core/scripts/xmlextras.js +++ /dev/null @@ -1,153 +0,0 @@ -// This is a third party JavaScript library from -// http://webfx.eae.net/dhtml/xmlextras/xmlextras.html -// i.e. This has not been written by ThoughtWorks. - -//<script> -////////////////// -// Helper Stuff // -////////////////// - -// used to find the Automation server name -function getDomDocumentPrefix() { - if (getDomDocumentPrefix.prefix) - return getDomDocumentPrefix.prefix; - - var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; - var o; - for (var i = 0; i < prefixes.length; i++) { - try { - // try to create the objects - o = new ActiveXObject(prefixes[i] + ".DomDocument"); - return getDomDocumentPrefix.prefix = prefixes[i]; - } - catch (ex) {}; - } - - throw new Error("Could not find an installed XML parser"); -} - -function getXmlHttpPrefix() { - if (getXmlHttpPrefix.prefix) - return getXmlHttpPrefix.prefix; - - var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; - var o; - for (var i = 0; i < prefixes.length; i++) { - try { - // try to create the objects - o = new ActiveXObject(prefixes[i] + ".XmlHttp"); - return getXmlHttpPrefix.prefix = prefixes[i]; - } - catch (ex) {}; - } - - throw new Error("Could not find an installed XML parser"); -} - -////////////////////////// -// Start the Real stuff // -////////////////////////// - - -// XmlHttp factory -function XmlHttp() {} - -XmlHttp.create = function () { - try { - if (window.XMLHttpRequest) { - var req = new XMLHttpRequest(); - - // some versions of Moz do not support the readyState property - // and the onreadystate event so we patch it! - if (req.readyState == null) { - req.readyState = 1; - req.addEventListener("load", function () { - req.readyState = 4; - if (typeof req.onreadystatechange == "function") - req.onreadystatechange(); - }, false); - } - - return req; - } - if (window.ActiveXObject) { - return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp"); - } - } - catch (ex) {} - // fell through - throw new Error("Your browser does not support XmlHttp objects"); -}; - -// XmlDocument factory -function XmlDocument() {} - -XmlDocument.create = function () { - try { - // DOM2 - if (document.implementation && document.implementation.createDocument) { - var doc = document.implementation.createDocument("", "", null); - - // some versions of Moz do not support the readyState property - // and the onreadystate event so we patch it! - if (doc.readyState == null) { - doc.readyState = 1; - doc.addEventListener("load", function () { - doc.readyState = 4; - if (typeof doc.onreadystatechange == "function") - doc.onreadystatechange(); - }, false); - } - - return doc; - } - if (window.ActiveXObject) - return new ActiveXObject(getDomDocumentPrefix() + ".DomDocument"); - } - catch (ex) {} - throw new Error("Your browser does not support XmlDocument objects"); -}; - -// Create the loadXML method and xml getter for Mozilla -if (window.DOMParser && - window.XMLSerializer && - window.Node && Node.prototype && Node.prototype.__defineGetter__) { - - // XMLDocument did not extend the Document interface in some versions - // of Mozilla. Extend both! - //XMLDocument.prototype.loadXML = - Document.prototype.loadXML = function (s) { - - // parse the string to a new doc - var doc2 = (new DOMParser()).parseFromString(s, "text/xml"); - - // remove all initial children - while (this.hasChildNodes()) - this.removeChild(this.lastChild); - - // insert and import nodes - for (var i = 0; i < doc2.childNodes.length; i++) { - this.appendChild(this.importNode(doc2.childNodes[i], true)); - } - }; - - - /* - * xml getter - * - * This serializes the DOM tree to an XML String - * - * Usage: var sXml = oNode.xml - * - */ - // XMLDocument did not extend the Document interface in some versions - // of Mozilla. Extend both! - /* - XMLDocument.prototype.__defineGetter__("xml", function () { - return (new XMLSerializer()).serializeToString(this); - }); - */ - Document.prototype.__defineGetter__("xml", function () { - return (new XMLSerializer()).serializeToString(this); - }); -}
\ No newline at end of file |