[Zope-CVS] CVS: Products/Zelenium/selenium -
user-extensions.js.sample:1.1 version.txt:1.1 xpath.js:1.1
html-xpath-patched.js:1.2 htmlutils.js:1.4
selenium-api.js:1.4 selenium-browserbot.js:1.4
selenium-executionloop.js:1.4 selenium-fitrunner.js:1.5
selenium-logging.js:1.3
Tres Seaver
tseaver at palladion.com
Tue Jun 7 13:18:18 EDT 2005
Update of /cvs-repository/Products/Zelenium/selenium
In directory cvs.zope.org:/tmp/cvs-serv2774/selenium
Modified Files:
html-xpath-patched.js htmlutils.js selenium-api.js
selenium-browserbot.js selenium-executionloop.js
selenium-fitrunner.js selenium-logging.js
Added Files:
user-extensions.js.sample version.txt xpath.js
Log Message:
- Begin using 'core application' from Selenium 0.4.0.
=== Added File Products/Zelenium/selenium/user-extensions.js.sample ===
/*
* 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.
*/
// 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
this.assertMatches(expectedValue, actualValue);
};
// 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;
};
=== Added File Products/Zelenium/selenium/version.txt ===
0.4.0
=== Added File Products/Zelenium/selenium/xpath.js === (3510/3910 lines abridged)
/*
* xpath.js
*
* An XPath 1.0 library for JavaScript.
*
* Cameron McCormack <cam (at) mcc.id.au>
*
* This work is licensed under the Creative Commons Attribution-ShareAlike
* License. To view a copy of this license, visit
* http://creativecommons.org/licenses/by-sa/2.0/ or send a letter to Creative
* Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
*
* Revision 13: May 3, 2005
* Node tests are case insensitive now if working in an HTML DOM.
*
* Revision 12: April 26, 2005
* Updated licence. Slight code changes to enable use of Dean
* Edwards' script compression, http://dean.edwards.name/packer/ .
*
* Revision 11: April 23, 2005
* Fixed bug with 'and' and 'or' operators, fix thanks to
* Sandy McArthur <sandy (at) mcarthur.org>.
*
* Revision 10: April 15, 2005
* Added support for a virtual root node, supposedly helpful for
* implementing XForms. Fixed problem with QName node tests and
* the parent axis.
*
* Revision 9: March 17, 2005
* Namespace resolver tweaked so using the document node as the context
* for namespace lookups is equivalent to using the document element.
*
* Revision 8: February 13, 2005
* Handle implicit declaration of 'xmlns' namespace prefix.
* Fixed bug when comparing nodesets.
* Instance data can now be associated with a FunctionResolver, and
* workaround for MSXML not supporting 'localName' and 'getElementById',
* thanks to Grant Gongaware.
* Fix a few problems when the context node is the root node.
*
* Revision 7: February 11, 2005
* Default namespace resolver fix from Grant Gongaware
* <grant (at) gongaware.com>.
*
* Revision 6: February 10, 2005
* Fixed bug in 'number' function.
*
* Revision 5: February 9, 2005
* Fixed bug where text nodes not getting converted to string values.
*
* Revision 4: January 21, 2005
* Bug in 'name' function, fix thanks to Bill Edney.
* Fixed incorrect processing of namespace nodes.
* Fixed NamespaceResolver to resolve 'xml' namespace.
* Implemented union '|' operator.
*
* Revision 3: January 14, 2005
* Fixed bug with nodeset comparisons, bug lexing < and >.
*
* Revision 2: October 26, 2004
* QName node test namespace handling fixed. Few other bug fixes.
*
* Revision 1: August 13, 2004
* Bug fixes from William J. Edney <bedney (at) technicalpursuit.com>.
* Added minimal licence.
*
* Initial version: June 14, 2004
*/
// XPathParser ///////////////////////////////////////////////////////////////
XPathParser.prototype = new Object();
XPathParser.prototype.constructor = XPathParser;
XPathParser.superclass = Object.prototype;
function XPathParser() {
this.init();
}
XPathParser.prototype.init = function() {
this.reduceActions = [];
this.reduceActions[3] = function(rhs) {
return new OrOperation(rhs[0], rhs[2]);
};
this.reduceActions[5] = function(rhs) {
return new AndOperation(rhs[0], rhs[2]);
};
this.reduceActions[7] = function(rhs) {
return new EqualsOperation(rhs[0], rhs[2]);
};
this.reduceActions[8] = function(rhs) {
return new NotEqualOperation(rhs[0], rhs[2]);
};
this.reduceActions[10] = function(rhs) {
return new LessThanOperation(rhs[0], rhs[2]);
};
this.reduceActions[11] = function(rhs) {
return new GreaterThanOperation(rhs[0], rhs[2]);
};
this.reduceActions[12] = function(rhs) {
return new LessThanOrEqualOperation(rhs[0], rhs[2]);
};
this.reduceActions[13] = function(rhs) {
return new GreaterThanOrEqualOperation(rhs[0], rhs[2]);
};
this.reduceActions[15] = function(rhs) {
return new PlusOperation(rhs[0], rhs[2]);
};
this.reduceActions[16] = function(rhs) {
return new MinusOperation(rhs[0], rhs[2]);
};
this.reduceActions[18] = function(rhs) {
return new MultiplyOperation(rhs[0], rhs[2]);
};
this.reduceActions[19] = function(rhs) {
return new DivOperation(rhs[0], rhs[2]);
};
this.reduceActions[20] = function(rhs) {
return new ModOperation(rhs[0], rhs[2]);
};
this.reduceActions[22] = function(rhs) {
return new UnaryMinusOperation(rhs[1]);
};
this.reduceActions[24] = function(rhs) {
return new BarOperation(rhs[0], rhs[2]);
};
this.reduceActions[25] = function(rhs) {
return new PathExpr(undefined, undefined, rhs[0]);
};
this.reduceActions[27] = function(rhs) {
rhs[0].locationPath = rhs[2];
return rhs[0];
};
this.reduceActions[28] = function(rhs) {
rhs[0].locationPath = rhs[2];
rhs[0].locationPath.steps.unshift(new Step(Step.DESCENDANTORSELF, new NodeTest(NodeTest.NODE, undefined), []));
return rhs[0];
};
this.reduceActions[29] = function(rhs) {
return new PathExpr(rhs[0], [], undefined);
};
this.reduceActions[30] = function(rhs) {
if (Utilities.instance_of(rhs[0], PathExpr)) {
if (rhs[0].filterPredicates == undefined) {
rhs[0].filterPredicates = [];
}
rhs[0].filterPredicates.push(rhs[1]);
return rhs[0];
} else {
return new PathExpr(rhs[0], [rhs[1]], undefined);
}
};
this.reduceActions[32] = function(rhs) {
return rhs[1];
};
this.reduceActions[33] = function(rhs) {
return new XString(rhs[0]);
};
this.reduceActions[34] = function(rhs) {
return new XNumber(rhs[0]);
};
this.reduceActions[36] = function(rhs) {
return new FunctionCall(rhs[0], []);
};
this.reduceActions[37] = function(rhs) {
return new FunctionCall(rhs[0], rhs[2]);
};
this.reduceActions[38] = function(rhs) {
return [ rhs[0] ];
};
this.reduceActions[39] = function(rhs) {
rhs[2].unshift(rhs[0]);
return rhs[2];
};
this.reduceActions[43] = function(rhs) {
return new LocationPath(true, []);
};
this.reduceActions[44] = function(rhs) {
rhs[1].absolute = true;
return rhs[1];
};
this.reduceActions[46] = function(rhs) {
return new LocationPath(false, [ rhs[0] ]);
};
this.reduceActions[47] = function(rhs) {
rhs[0].steps.push(rhs[2]);
return rhs[0];
};
this.reduceActions[49] = function(rhs) {
return new Step(rhs[0], rhs[1], []);
};
this.reduceActions[50] = function(rhs) {
return new Step(Step.CHILD, rhs[0], []);
};
this.reduceActions[51] = function(rhs) {
return new Step(rhs[0], rhs[1], rhs[2]);
};
this.reduceActions[52] = function(rhs) {
return new Step(Step.CHILD, rhs[0], rhs[1]);
[-=- -=- -=- 3510 lines omitted -=- -=- -=-]
c >= 0x30A1 && c <= 0x30FA ||
c >= 0x3105 && c <= 0x312C ||
c >= 0xAC00 && c <= 0xD7A3 ||
c >= 0x4E00 && c <= 0x9FA5 ||
c == 0x3007 ||
c >= 0x3021 && c <= 0x3029;
};
Utilities.isNCNameChar = function(c) {
return c >= 0x0030 && c <= 0x0039
|| c >= 0x0660 && c <= 0x0669
|| c >= 0x06F0 && c <= 0x06F9
|| c >= 0x0966 && c <= 0x096F
|| c >= 0x09E6 && c <= 0x09EF
|| c >= 0x0A66 && c <= 0x0A6F
|| c >= 0x0AE6 && c <= 0x0AEF
|| c >= 0x0B66 && c <= 0x0B6F
|| c >= 0x0BE7 && c <= 0x0BEF
|| c >= 0x0C66 && c <= 0x0C6F
|| c >= 0x0CE6 && c <= 0x0CEF
|| c >= 0x0D66 && c <= 0x0D6F
|| c >= 0x0E50 && c <= 0x0E59
|| c >= 0x0ED0 && c <= 0x0ED9
|| c >= 0x0F20 && c <= 0x0F29
|| c == 0x002E
|| c == 0x002D
|| c == 0x005F
|| Utilities.isLetter(c)
|| c >= 0x0300 && c <= 0x0345
|| c >= 0x0360 && c <= 0x0361
|| c >= 0x0483 && c <= 0x0486
|| c >= 0x0591 && c <= 0x05A1
|| c >= 0x05A3 && c <= 0x05B9
|| c >= 0x05BB && c <= 0x05BD
|| c == 0x05BF
|| c >= 0x05C1 && c <= 0x05C2
|| c == 0x05C4
|| c >= 0x064B && c <= 0x0652
|| c == 0x0670
|| c >= 0x06D6 && c <= 0x06DC
|| c >= 0x06DD && c <= 0x06DF
|| c >= 0x06E0 && c <= 0x06E4
|| c >= 0x06E7 && c <= 0x06E8
|| c >= 0x06EA && c <= 0x06ED
|| c >= 0x0901 && c <= 0x0903
|| c == 0x093C
|| c >= 0x093E && c <= 0x094C
|| c == 0x094D
|| c >= 0x0951 && c <= 0x0954
|| c >= 0x0962 && c <= 0x0963
|| c >= 0x0981 && c <= 0x0983
|| c == 0x09BC
|| c == 0x09BE
|| c == 0x09BF
|| c >= 0x09C0 && c <= 0x09C4
|| c >= 0x09C7 && c <= 0x09C8
|| c >= 0x09CB && c <= 0x09CD
|| c == 0x09D7
|| c >= 0x09E2 && c <= 0x09E3
|| c == 0x0A02
|| c == 0x0A3C
|| c == 0x0A3E
|| c == 0x0A3F
|| c >= 0x0A40 && c <= 0x0A42
|| c >= 0x0A47 && c <= 0x0A48
|| c >= 0x0A4B && c <= 0x0A4D
|| c >= 0x0A70 && c <= 0x0A71
|| c >= 0x0A81 && c <= 0x0A83
|| c == 0x0ABC
|| c >= 0x0ABE && c <= 0x0AC5
|| c >= 0x0AC7 && c <= 0x0AC9
|| c >= 0x0ACB && c <= 0x0ACD
|| c >= 0x0B01 && c <= 0x0B03
|| c == 0x0B3C
|| c >= 0x0B3E && c <= 0x0B43
|| c >= 0x0B47 && c <= 0x0B48
|| c >= 0x0B4B && c <= 0x0B4D
|| c >= 0x0B56 && c <= 0x0B57
|| c >= 0x0B82 && c <= 0x0B83
|| c >= 0x0BBE && c <= 0x0BC2
|| c >= 0x0BC6 && c <= 0x0BC8
|| c >= 0x0BCA && c <= 0x0BCD
|| c == 0x0BD7
|| c >= 0x0C01 && c <= 0x0C03
|| c >= 0x0C3E && c <= 0x0C44
|| c >= 0x0C46 && c <= 0x0C48
|| c >= 0x0C4A && c <= 0x0C4D
|| c >= 0x0C55 && c <= 0x0C56
|| c >= 0x0C82 && c <= 0x0C83
|| c >= 0x0CBE && c <= 0x0CC4
|| c >= 0x0CC6 && c <= 0x0CC8
|| c >= 0x0CCA && c <= 0x0CCD
|| c >= 0x0CD5 && c <= 0x0CD6
|| c >= 0x0D02 && c <= 0x0D03
|| c >= 0x0D3E && c <= 0x0D43
|| c >= 0x0D46 && c <= 0x0D48
|| c >= 0x0D4A && c <= 0x0D4D
|| c == 0x0D57
|| c == 0x0E31
|| c >= 0x0E34 && c <= 0x0E3A
|| c >= 0x0E47 && c <= 0x0E4E
|| c == 0x0EB1
|| c >= 0x0EB4 && c <= 0x0EB9
|| c >= 0x0EBB && c <= 0x0EBC
|| c >= 0x0EC8 && c <= 0x0ECD
|| c >= 0x0F18 && c <= 0x0F19
|| c == 0x0F35
|| c == 0x0F37
|| c == 0x0F39
|| c == 0x0F3E
|| c == 0x0F3F
|| c >= 0x0F71 && c <= 0x0F84
|| c >= 0x0F86 && c <= 0x0F8B
|| c >= 0x0F90 && c <= 0x0F95
|| c == 0x0F97
|| c >= 0x0F99 && c <= 0x0FAD
|| c >= 0x0FB1 && c <= 0x0FB7
|| c == 0x0FB9
|| c >= 0x20D0 && c <= 0x20DC
|| c == 0x20E1
|| c >= 0x302A && c <= 0x302F
|| c == 0x3099
|| c == 0x309A
|| c == 0x00B7
|| c == 0x02D0
|| c == 0x02D1
|| c == 0x0387
|| c == 0x0640
|| c == 0x0E46
|| c == 0x0EC6
|| c == 0x3005
|| c >= 0x3031 && c <= 0x3035
|| c >= 0x309D && c <= 0x309E
|| c >= 0x30FC && c <= 0x30FE;
};
Utilities.coalesceText = function(n) {
for (var m = n.firstChild; m != null; m = m.nextSibling) {
if (m.nodeType == 3 /*Node.TEXT_NODE*/ || m.nodeType == 4 /*Node.CDATA_SECTION_NODE*/) {
var s = m.nodeValue;
var first = m;
m = m.nextSibling;
while (m != null && (m.nodeType == 3 /*Node.TEXT_NODE*/ || m.nodeType == 4 /*Node.CDATA_SECTION_NODE*/)) {
s += m.nodeValue;
var del = m;
m = m.nextSibling;
del.parentNode.removeChild(del);
}
if (first.nodeType == 4 /*Node.CDATA_SECTION_NODE*/) {
var p = first.parentNode;
if (first.nextSibling == null) {
p.removeChild(first);
p.appendChild(p.ownerDocument.createTextNode(s));
} else {
var next = first.nextSibling;
p.removeChild(first);
p.insertBefore(p.ownerDocument.createTextNode(s), next);
}
} else {
first.nodeValue = s;
}
if (m == null) {
break;
}
} else if (m.nodeType == 1 /*Node.ELEMENT_NODE*/) {
Utilities.coalesceText(m);
}
}
};
Utilities.instance_of = function(o, c) {
while (o != null) {
if (o.constructor === c) {
return true;
}
if (o === Object) {
return false;
}
o = o.constructor.superclass;
}
return false;
};
Utilities.getElementById = function(n, id) {
// Note that this does not check the DTD to check for actual
// attributes of type ID, so this may be a bit wrong.
if (n.nodeType == 1 /*Node.ELEMENT_NODE*/) {
if (n.getAttribute("id") == id
|| n.getAttributeNS(null, "id") == id) {
return n;
}
}
for (var m = n.firstChild; m != null; m = m.nextSibling) {
var res = Utilities.getElementById(m, id);
if (res != null) {
return res;
}
}
return null;
};
=== Products/Zelenium/selenium/html-xpath-patched.js 1.1.1.1 => 1.2 ===
--- Products/Zelenium/selenium/html-xpath-patched.js:1.1.1.1 Fri Apr 15 14:48:45 2005
+++ Products/Zelenium/selenium/html-xpath-patched.js Tue Jun 7 13:17:46 2005
@@ -536,11 +536,45 @@
{
return loadNode(dom, dom, document.body, helper);
}
-
+
+
+/** SELENIUM:PATCH for loadNode() - see SEL-68 */
function loadNode(dom, domParentNode, node, helper)
{
- if (node.nodeType == 3)
- {
+ // Bad node scenarios
+ // 1. If the node contains a /, it's broken HTML
+ // 2. If the node doesn't have a name (typically from broken HTML), the node can't be loaded
+ // 3. Node types we can't deal with
+ //
+ // In all scenarios, we just skip the node. We won't be able to
+ // query on these nodes, but they're broken anyway.
+ if (node.nodeName.indexOf("/") > -1
+ || node.nodeName == ""
+ || node.nodeName == "#document"
+ || node.nodeName == "#document-fragment"
+ || node.nodeName == "#cdata-section"
+ || node.nodeName == "#xml-declaration"
+ || node.nodeName == "#whitespace"
+ || node.nodeName == "#significat-whitespace"
+ )
+ {
+ return;
+ }
+
+ // #comment is a <!-- comment -->, which must be created with createComment()
+ if (node.nodeName == "#comment")
+ {
+ try
+ {
+ domParentNode.appendChild(dom.createComment(node.nodeValue));
+ }
+ catch (ex)
+ {
+ // it's just a comment, we don't care
+ }
+ }
+ else if (node.nodeType == 3)
+ {
domParentNode.appendChild(dom.createTextNode(node.nodeValue));
}
else
@@ -560,6 +594,7 @@
node.attachEvent("onpropertychange", onPropertyChangeEventHandler);
}
}
+/** END SELENIUM:PATCH */
function loadAttributes(dom, domParentNode, node)
{
=== Products/Zelenium/selenium/htmlutils.js 1.3 => 1.4 ===
--- Products/Zelenium/selenium/htmlutils.js:1.3 Fri May 6 07:46:12 2005
+++ Products/Zelenium/selenium/htmlutils.js Tue Jun 7 13:17:46 2005
@@ -44,6 +44,9 @@
} else if(element.innerText) {
text = element.innerText;
}
+ // Replace with a space
+ // TODO - should this be in the match() code instead?
+ text = text.replace(/\240/g, " ");
return text.trim();
}
@@ -104,6 +107,13 @@
element.addEventListener("load",command, true);
else if (window.attachEvent)
element.attachEvent("onload",command);
+}
+
+function addUnloadListener(element, command) {
+ if (window.addEventListener)
+ element.addEventListener("unload",command, true);
+ else if (window.attachEvent)
+ element.attachEvent("onunload",command);
}
/**
=== Products/Zelenium/selenium/selenium-api.js 1.3 => 1.4 ===
--- Products/Zelenium/selenium/selenium-api.js:1.3 Fri May 6 07:46:12 2005
+++ Products/Zelenium/selenium/selenium-api.js Tue Jun 7 13:17:46 2005
@@ -15,6 +15,8 @@
*
*/
+storedVars = new Object();
+
var nextExecution;
function executeNext() {
LOG.debug("CODED - LOAD");
@@ -40,6 +42,14 @@
}
/*
+ * Reset the browserbot when an error occurs..
+ */
+Selenium.prototype.reset = function() {
+ storedVars = new Object();
+ this.browserbot.selectWindow("null");
+};
+
+/*
* Click on the located element, and attach a callback to notify
* when the page is reloaded.
*/
@@ -221,22 +231,26 @@
this.assertMatches(expectedLabel, selectedLabel);
};
+String.prototype.parseCSV = function() {
+ var values = this.replace(/\\,/g, "\n").split(",");
+ // Restore escaped commas
+ for (var i = 0; i < values.length; i++) {
+ values[i] = values[i].replace(/\n/g, ",").trim();
+ }
+ return values;
+};
+
/**
* Verify the label of all of the options in the drop=down.
*/
Selenium.prototype.assertSelectOptions = function(target, options) {
- // Handle escpaced commas, by substitutine newlines.
- options = options.replace("\\,", "\n");
- var expectedOptions = options.split(",");
var element = this.page().findElement(target);
- assert.equals("Wrong number of options.", expectedOptions.length, element.options.length);
+ var expectedOptionLabels = options.parseCSV();
+ assert.equals("Wrong number of options.", expectedOptionLabels.length, element.options.length);
for (var i = 0; i < element.options.length; i++) {
- var option = element.options[i];
- // Put the escaped commas back in.
- var expectedOption = expectedOptions[i].replace("\n", ",");
- this.assertMatches(expectedOption, option.text);
+ this.assertMatches(expectedOptionLabels[i], element.options[i].text);
}
};
@@ -420,10 +434,77 @@
};
/*
- * Set the context for the current Test
- */
+ * Set the context for the current Test
+ */
Selenium.prototype.doContext = function(context) {
return this.page().setContext(context);
+};
+
+/*
+ * Store the value of a form input in a variable
+ */
+Selenium.prototype.doStoreValue = function(target, varName) {
+ if (!varName) {
+ // Backward compatibility mode: read the ENTIRE text of the page
+ // and stores it in a variable with the name of the target
+ value = this.page().bodyText();
+ storedVars[target] = value;
+ return;
+ }
+ var element = this.page().findElement(target);
+ storedVars[varName] = getInputValue(element);
+};
+
+/*
+ * Store the text of an element in a variable
+ */
+Selenium.prototype.doStoreText = function(target, varName) {
+ var element = this.page().findElement(target);
+ storedVars[varName] = getText(element);
+};
+
+/*
+ * Store the result of a literal value
+ */
+Selenium.prototype.doStore = function(value, varName) {
+ storedVars[varName] = value;
+};
+
+/**
+ * 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\{(.+)\}$/);
+ 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;
};
function Assert() {
=== Products/Zelenium/selenium/selenium-browserbot.js 1.3 => 1.4 ===
--- Products/Zelenium/selenium/selenium-browserbot.js:1.3 Fri May 6 07:46:12 2005
+++ Products/Zelenium/selenium/selenium-browserbot.js Tue Jun 7 13:17:46 2005
@@ -42,19 +42,19 @@
var geckoResult = /^Mozilla\/5\.0 .*Gecko\/(\d{8}).*$/.exec(navigator.userAgent);
var geckoVersion = geckoResult == null ? null : geckoResult[1];
-function createBrowserBot(frame, executionContext) {
+function createBrowserBot(frame) {
if (isIE) {
- return new IEBrowserBot(frame, executionContext);
+ return new IEBrowserBot(frame);
}
else if (isKonqueror) {
- return new KonquerorBrowserBot(frame, executionContext);
+ return new KonquerorBrowserBot(frame);
}
else if (isSafari) {
- return new SafariBrowserBot(frame, executionContext);
+ return new SafariBrowserBot(frame);
}
else {
// Use mozilla by default
- return new MozillaBrowserBot(frame, executionContext);
+ return new MozillaBrowserBot(frame);
}
}
@@ -74,9 +74,8 @@
}
}
-BrowserBot = function(frame, executionContext) {
+BrowserBot = function(frame) {
this.frame = frame;
- this.executionContext = executionContext;
this.currentPage = null;
this.currentWindowName = null;
@@ -115,16 +114,11 @@
return this.frame;
};
-BrowserBot.prototype.getContentWindow = function() {
- return this.executionContext.getContentWindow(this.getFrame());
-
-};
-
BrowserBot.prototype.selectWindow = function(target) {
// we've moved to a new page - clear the current one
this.currentPage = null;
this.currentWindowName = null;
- if (target != "null") {
+ if (target && target != "null") {
// If window exists
if (this.getTargetWindow(target)) {
this.currentWindowName = target;
@@ -135,15 +129,15 @@
BrowserBot.prototype.openLocation = function(target, onloadCallback) {
// We're moving to a new page - clear the current one
this.currentPage = null;
- this.executionContext.open(target,this.getFrame());
+ // Window doesn't fire onload event when setting src to the current value,
+ // so we set it to blank first.
+ this.getFrame().src = "about:blank";
+ this.getFrame().src = target;
};
BrowserBot.prototype.getCurrentPage = function() {
if (this.currentPage == null) {
- var testWindow = this.getContentWindow().window;
- if (this.currentWindowName != null) {
- testWindow = this.getTargetWindow(this.currentWindowName);
- }
+ var testWindow = this.getCurrentWindow();
this.modifyWindowToRecordPopUpDialogs(testWindow, this);
this.modifyWindowToClearPageCache(testWindow, this);
this.currentPage = createPageBot(testWindow);
@@ -178,6 +172,10 @@
}
};
+BrowserBot.prototype.getContentWindow = function() {
+ return this.getFrame().contentWindow || frames[this.getFrame().id];
+};
+
BrowserBot.prototype.getTargetWindow = function(windowName) {
var evalString = "this.getContentWindow().window." + windowName;
var targetWindow = eval(evalString);
@@ -187,22 +185,89 @@
return targetWindow;
};
+BrowserBot.prototype.getCurrentWindow = function() {
+ var testWindow = this.getContentWindow().window;
+ if (this.currentWindowName != null) {
+ testWindow = this.getTargetWindow(this.currentWindowName);
+ }
+ return testWindow;
+};
+
BrowserBot.prototype.callOnNextPageLoad = function(onloadCallback) {
- addLoadListener(this.frame, onloadCallback);
+ if (this.currentWindowName == null) {
+ this.callOnFramePageTransition(onloadCallback, this.getFrame());
+ }
+ else {
+ this.callOnWindowPageTransition(onloadCallback, this.getCurrentWindow());
+ }
+};
+
+BrowserBot.prototype.callOnFramePageTransition = function(loadFunction, frameObject) {
+ try {
+ addLoadListener(frameObject, loadFunction);
+ } catch (e) {
+ LOG.debug("Got on error adding LoadListener in BrowserBot.prototype.callOnFramePageTransition." +
+ "This occurs on the second and all subsequent calls in Safari");
+ }
+};
+
+BrowserBot.prototype.callOnWindowPageTransition = function(loadFunction, windowObject) {
+ var unloadFunction = function() {
+ window.setTimeout(function() {addLoadListener(windowObject, loadFunction);}, 0);
+ };
+ addUnloadListener(windowObject, unloadFunction);
};
-function MozillaBrowserBot(frame, executionContext) {
- BrowserBot.call(this, frame, executionContext);
+/**
+ * Handle the initial page load in a new popup window.
+ * TODO - something like this should allow us to wait for a new popup window - currently need to pause...
+ */
+//function callOnWindowInitialLoad(loadFunction, windowObject) {
+// if (!(isSafari || isKonqueror)) {
+// addLoadListener(windowObject, loadFunction);
+// }
+// else {
+// this.pollForLoad(loadFunction, windowObject, windowObject.document);
+// }
+//}
+
+function MozillaBrowserBot(frame) {
+ BrowserBot.call(this, frame);
}
MozillaBrowserBot.prototype = new BrowserBot;
-function KonquerorBrowserBot(frame, executionContext) {
- BrowserBot.call(this, frame, executionContext);
+function KonquerorBrowserBot(frame) {
+ BrowserBot.call(this, frame);
}
KonquerorBrowserBot.prototype = new BrowserBot;
-function SafariBrowserBot(frame, executionContext) {
- BrowserBot.call(this, frame, executionContext);
+KonquerorBrowserBot.prototype.callOnWindowPageTransition = function(loadFunction, windowObject) {
+ // Since the unload event doesn't fire in Safari 1.3, we start polling immediately
+ // This works in Konqueror as well
+ this.pollForLoad(loadFunction, windowObject, windowObject.document);
+};
+
+/**
+ * For Konqueror (and Safari), we can't catch the onload event for a separate window (as opposed to an IFrame)
+ * So we 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 check to see that the completed document
+ * is different from the original one.
+ */
+KonquerorBrowserBot.prototype.pollForLoad = function(loadFunction, windowObject, originalDocument) {
+ var sameDoc = (originalDocument === windowObject.document);
+ var rs = windowObject.document.readyState;
+
+ if (!sameDoc && rs == 'complete') {
+ LOG.debug("poll: " + rs + " (" + sameDoc + ")");
+ loadFunction();
+ return;
+ }
+ var self = this;
+ window.setTimeout(function() {self.pollForLoad(loadFunction, windowObject, originalDocument);}, 100);
+};
+
+function SafariBrowserBot(frame) {
+ BrowserBot.call(this, frame);
}
SafariBrowserBot.prototype = new BrowserBot;
@@ -212,17 +277,14 @@
*/
SafariBrowserBot.prototype.callOnNextPageLoad = function(onloadCallback) {
this.currentPage = null;
-
- try {
- addLoadListener(this.frame, onloadCallback);
- } catch (e) {
- LOG.debug("Got on error adding LoadListener in BrowserBot.prototype.callOnNextPageLoad." +
- "This occurs on the second and all subsequent calls in Safari");
- }
+ BrowserBot.prototype.callOnNextPageLoad.call(this, onloadCallback);
};
-function IEBrowserBot(frame, executionContext) {
- BrowserBot.call(this, frame, executionContext);
+SafariBrowserBot.prototype.callOnWindowPageTransition = KonquerorBrowserBot.prototype.callOnWindowPageTransition;
+SafariBrowserBot.prototype.pollForLoad = KonquerorBrowserBot.prototype.pollForLoad;
+
+function IEBrowserBot(frame) {
+ BrowserBot.call(this, frame);
}
IEBrowserBot.prototype = new BrowserBot;
@@ -281,15 +343,45 @@
this.currentDocument = pageWindow.document;
this.location = pageWindow.location.pathname;
this.title = function() {return this.currentDocument.title;};
+ }
- // Register all locate* functions
- this.locatorFunctions = new Array();
- for (var f in this) {
- if (typeof(this[f]) == 'function' && f.match(/^locate/)) {
- this.locatorFunctions.push(this[f]);
+ // Register all locateElementBy* functions
+ // 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) {
+ var locatorFunction = this.locationStrategies[locatorType];
+ if (! locatorFunction) {
+ throw new Error("Unrecognised locator type: '" + locatorType + "'");
+ }
+ return locatorFunction.call(this, locator, inDocument);
+ };
+
+ /**
+ * The implicit locator, that is used when no prefix is supplied.
+ */
+ this.locationStrategies['implicit'] = function(locator, inDocument) {
+ return this.locateElementByIdentifier(locator, inDocument)
+ || this.locateElementByDomTraversal(locator, inDocument)
+ || this.locateElementByXPath(locator, inDocument);
+ };
+
};
MozillaPageBot = function(pageWindow) {
@@ -316,16 +408,24 @@
* Finds an element on the current page, using various lookup protocols
*/
PageBot.prototype.findElement = function(locator) {
- var element = this.findElementInDocument(locator, this.currentDocument);
+ var locatorType = 'implicit';
+ var locatorString = locator;
+
+ // If there is a locator prefix, use the specified strategy
+ var result = locator.match(/^([a-z]+)=(.+)/);
+ if (result) {
+ locatorType = result[1];
+ locatorString = result[2];
+ }
+ var element = this.findElementBy(locatorType, locatorString, this.currentDocument);
if (element != null) {
return element;
- } else {
- for (var i = 0; i < this.currentWindow.frames.length; i++) {
- element = this.findElementInDocument(locator, this.currentWindow.frames[i].document);
- if (element != null) {
- return element;
- }
+ }
+ for (var i = 0; i < this.currentWindow.frames.length; i++) {
+ element = this.findElementBy(locatorType, locatorString, this.currentWindow.frames[i].document);
+ if (element != null) {
+ return element;
}
}
@@ -333,59 +433,49 @@
throw new Error("Element " + locator + " not found");
};
-PageBot.prototype.findElementInDocument = function(locator, inDocument) {
- // Try the locatorFunctions one at a time.
- for (var i = 0; i < this.locatorFunctions.length; i++) {
- var locatorFunction = this.locatorFunctions[i];
- var element = locatorFunction.call(this, locator, inDocument);
- if (element != null) {
- return element;
- }
- }
+/**
+ * In non-IE browsers, getElementById() does not search by name. Instead, we
+ * we search separately by id and name.
+ */
+PageBot.prototype.locateElementByIdentifier = function(identifier, inDocument) {
+ return PageBot.prototype.locateElementById(identifier, inDocument)
+ || PageBot.prototype.locateElementByName(identifier, inDocument)
+ || null;
};
/**
- * In IE, getElementById() also searches by name.
+ * In IE, getElementById() also searches by name - this is an optimisation for IE.
*/
-IEPageBot.prototype.locateElementById = function(identifier, inDocument) {
- try {
- return inDocument.getElementById(identifier);
- } catch (e) {
- return null;
- }
+IEPageBot.prototype.locateElementByIdentifer = function(identifier, inDocument) {
+ return inDocument.getElementById(identifier);
};
/**
- * In other browsers, getElementById() does not search by name. To provide
- * functionality consistent with IE, we search by @name if an element with
- * the @id isn't found.
+ * Find the element with id - can't rely on getElementById, coz it returns by name as well in IE..
*/
PageBot.prototype.locateElementById = function(identifier, inDocument) {
- try {
- var element = inDocument.getElementById(identifier);
- if (element == null)
- {
- if ( document.evaluate ) {// DOM3 XPath
- var xpath = "//*[@name='" + identifier + "']";
- element = document.evaluate(xpath, inDocument, null, 0, null).iterateNext();
- }
- // Search through all elements for Konqueror/Safari
- else {
- var allElements = inDocument.getElementsByTagName("*");
- for (var i = 0; i < allElements.length; i++) {
- var testElement = allElements[i];
- if (testElement.name && testElement.name === identifier) {
- element = testElement;
- break;
- }
- }
- }
- }
- } catch (e) {
+ var element = inDocument.getElementById(identifier);
+ if (element && element.id === identifier) {
+ return element;
+ }
+ else {
return null;
}
+};
- return element;
+/**
+ * In regular browsers, getElementById() does not search by name.
+ * We search by @name using XPath, or by checking every element.
+ */
+PageBot.prototype.locateElementByName = function(identifier, inDocument) {
+ var allElements = inDocument.getElementsByTagName("*");
+ for (var i = 0; i < allElements.length; i++) {
+ var testElement = allElements[i];
+ if (testElement.name && testElement.name === identifier) {
+ return testElement;
+ }
+ }
+ return null;
};
/**
@@ -408,56 +498,108 @@
return element;
};
+PageBot.prototype.locateElementByDomTraversal.prefix = "dom";
/**
* Finds an element identified by the xpath expression. Expressions _must_
* begin with "//".
*/
PageBot.prototype.locateElementByXPath = function(xpath, inDocument) {
- if (xpath.indexOf("//") != 0) {
+ if (xpath.slice(0,2) != "//") {
return null;
}
- // If don't have XPath bail.
- // TODO implement subset of XPath for browsers without native support.
- if (!inDocument.evaluate) {
- throw new Error("XPath not supported");
- }
-
- // Trim any trailing "/": not valid xpath, and remains from attribute locator.
+ // Trim any trailing "/": not valid xpath, and remains from attribute
+ // locator.
if (xpath.charAt(xpath.length - 1) == '/') {
- xpath = xpath.slice(0, xpath.length - 1);
+ xpath = xpath.slice(0, -1);
}
- return inDocument.evaluate(xpath, inDocument, null, 0, null).iterateNext();
+ // 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) {
+ return this.findElementByTagNameAndAttributeValue(
+ inDocument,
+ match[1].toUpperCase(),
+ match[2].toLowerCase(),
+ match[3].slice(1, -1)
+ );
+ }
+
+ // 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);
+};
+
+PageBot.prototype.findElementByTagNameAndAttributeValue = function(
+ inDocument, tagName, attributeName, attributeValue
+) {
+ if (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;
};
-/**
- * For IE, we implement XPath support using the html-xpath library.
- */
-IEPageBot.prototype.locateElementByXPath = function(xpath, inDocument) {
- if (xpath.indexOf("//") != 0) {
- return null;
- }
+PageBot.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;
+};
- if (!inDocument.evaluate) {
+PageBot.prototype.findElementUsingFullXPath = function(xpath, inDocument) {
+ if (isIE && !inDocument.evaluate) {
addXPathSupport(inDocument);
}
- return PageBot.prototype.locateElementByXPath(xpath, inDocument);
+ // Use document.evaluate() if it's available
+ if (inDocument.evaluate) {
+ return inDocument.evaluate(xpath, inDocument, null, 0, null).iterateNext();
+ }
+
+ // If not, fall back to slower JavaScript implementation
+ var context = new XPathContext();
+ context.expressionContextNode = inDocument;
+ var xpathResult = new XPathParser().parse(xpath).evaluate(context);
+ if (xpathResult && xpathResult.toArray) {
+ return xpathResult.toArray()[0];
+ }
+ return null;
};
/**
* Finds a link element with text matching the expression supplied. Expressions must
* begin with "link:".
*/
-PageBot.prototype.locateLinkByText = function(linkDescription, inDocument) {
- var prefix = "link:";
- if (linkDescription.indexOf(prefix) != 0) {
- return null;
- }
-
- var linkText = linkDescription.substring(prefix.length);
+PageBot.prototype.locateElementByLinkText = function(linkText, inDocument) {
var links = inDocument.getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
var element = links[i];
@@ -467,6 +609,7 @@
}
return null;
};
+PageBot.prototype.locateElementByLinkText.prefix = "link";
/**
* Returns an attribute based on an attribute locator. This is made up of an element locator
=== Products/Zelenium/selenium/selenium-executionloop.js 1.3 => 1.4 ===
--- Products/Zelenium/selenium/selenium-executionloop.js:1.3 Fri May 6 07:46:12 2005
+++ Products/Zelenium/selenium/selenium-executionloop.js Tue Jun 7 13:17:46 2005
@@ -20,12 +20,13 @@
TEST_FINISHED = true;
TEST_CONTINUE = false;
-function TestLoop(commandFactory, executionContext) {
+function TestLoop(commandFactory) {
this.commandFactory = commandFactory;
var self = this;
this.start = function() {
+ selenium.reset();
this.continueCurrentTest();
};
@@ -35,7 +36,7 @@
if (testStatus == TEST_FINISHED) {
this.testComplete();
}
- };
+ };
this.kickoffNextCommandExecution = function() {
@@ -58,9 +59,12 @@
try {
var handler = this.commandFactory.getCommandHandler(command.command);
if(handler == null) {
- throw new Error("Unknown command");
+ throw new Error("Unknown command: '" + command.command + "'");
}
+ command.target = selenium.preprocessParameter(command.target);
+ command.value = selenium.preprocessParameter(command.value);
+
result = handler.execute(selenium, command);
} catch (e) {
LOG.error(e);
@@ -77,8 +81,12 @@
// Record the result so that we can continue the execution using window.setTimeout()
this.lastCommandResult = result;
if (result.processState == SELENIUM_PROCESS_WAIT) {
+ // Since we're waiting for page to reload, we can't continue command execution
+ // directly, we need use a page load listener.
- executionContext.waitForPageLoad(this,selenium);
+ // TODO there is a potential race condition by attaching a load listener after
+ // the command has completed execution.
+ selenium.callOnNextPageLoad(function() {eval("testLoop.continueCommandExecutionWithDelay()");});
} else {
// Continue processing
@@ -93,13 +101,17 @@
* Continues the command execution, after waiting for the specified delay.
*/
this.continueCommandExecutionWithDelay = function() {
- // Get the interval to use for this command execution, using the pauseInterval is
+ // Get the interval to use for this command execution, using the pauseInterval as
// specified. Reset the pause interval, since it's a one-off thing.
var interval = this.pauseInterval || this.getCommandInterval();
this.pauseInterval = undefined;
- // Continue processing
- if (interval >= 0) {
+ if (interval < 0) {
+ // Enable the "next/continue" button
+ this.waitingForNext();
+ }
+ else {
+ // Continue processing
window.setTimeout("testLoop.finishCommandExecution()", interval);
}
};
@@ -129,6 +141,8 @@
TestLoop.prototype.commandComplete = noop;
TestLoop.prototype.testComplete = noop;
+
+TestLoop.prototype.waitingForNext = noop;
function noop() {
=== Products/Zelenium/selenium/selenium-fitrunner.js 1.4 => 1.5 ===
--- Products/Zelenium/selenium/selenium-fitrunner.js:1.4 Fri May 6 07:47:06 2005
+++ Products/Zelenium/selenium/selenium-fitrunner.js Tue Jun 7 13:17:46 2005
@@ -33,9 +33,6 @@
testFailed = false;
suiteFailed = false;
-// Holds variables that are stored in a script
-storedVars = new Object();
-
// Holds the handlers for each command.
commandHandlers = null;
@@ -67,10 +64,19 @@
runInterval = 0;
function setRunInterval() {
- runInterval = this.value;
+ // Get the value of the checked runMode option.
+ // There should be a way of getting the value of the "group", but I don't know how.
+ var runModeOptions = document.forms['controlPanel'].runMode;
+ for (var i = 0; i < runModeOptions.length; i++) {
+ if (runModeOptions[i].checked) {
+ runInterval = runModeOptions[i].value;
+ break;
+ }
+ }
}
function continueCurrentTest() {
+ document.getElementById('continueTest').disabled = true;
testLoop.finishCommandExecution();
}
@@ -90,26 +96,14 @@
loadSuiteFrame();
}
-function getExecutionContext() {
- if (isNewWindow()) {
- return getWindowExecutionContext();
- }
- else if (isSafari || isKonqueror) {
- return new KonquerorIFrameExecutionContext();
- }
- else {
- return new IFrameExecutionContext();
- }
-}
-
function start() {
- loadSuiteFrame(getExecutionContext());
+ setRunInterval();
+ loadSuiteFrame();
}
-function loadSuiteFrame(executionContext) {
-
- var testAppFrame = executionContext.loadFrame();
- browserbot = createBrowserBot(testAppFrame,executionContext);
+function loadSuiteFrame() {
+ var testAppFrame = document.getElementById('myiframe');
+ browserbot = createBrowserBot(testAppFrame);
selenium = new Selenium(browserbot);
registerCommandHandlers();
@@ -337,8 +331,13 @@
testLink = suiteTable.rows[currentTestRow].cells[0].getElementsByTagName("a")[0];
testLink.focus();
- addLoadListener(getTestFrame(), startTest);
- getExecutionContext().open(testLink.href, getTestFrame());
+ var testFrame = getTestFrame();
+ addLoadListener(testFrame, startTest);
+
+ // Window doesn't fire onload event when setting src to the current value,
+ // so we set it to blank first.
+ testFrame.src = "about:blank";
+ testFrame.src = testLink.href;
}
}
@@ -473,24 +472,6 @@
}
/*
- * Search through str and replace all variable references ${varName} with their
- * value in storedVars.
- */
-function replaceVariables(str) {
- // We can't use a String.replace(regexp, replacementFunction) since this doesn't
- // work in safari. So replace each match 1 at a time.
- var stringResult = str;
- var match;
- while (match = stringResult.match(/\$\{(\w+)\}/)) {
- var variable = match[0];
- var name = match[1];
- var replacement = storedVars[name];
- stringResult = stringResult.replace(variable, replacement);
- }
- return stringResult;
-}
-
-/*
* Register all of the built-in command handlers with the CommandHandlerFactory.
* TODO work out an easy way for people to register handlers without modifying the Selenium sources.
*/
@@ -498,14 +479,10 @@
commandFactory = new CommandHandlerFactory();
commandFactory.registerAll(selenium);
- // These actions are overridden for fitrunner, as they still involve some FitRunner smarts,
- // because of the wait/nowait behaviour modification. We need a generic solution to this.
- commandFactory.registerAction("click", selenium.doClickWithOptionalWait);
-
}
function initialiseTestLoop() {
- testLoop = new TestLoop(commandFactory, getExecutionContext());
+ testLoop = new TestLoop(commandFactory);
testLoop.getCommandInterval = function() { return runInterval; };
testLoop.firstCommand = nextCommand;
@@ -514,6 +491,9 @@
testLoop.commandComplete = commandComplete;
testLoop.commandError = commandError;
testLoop.testComplete = testComplete;
+ testLoop.waitingForNext = function() {
+ document.getElementById('continueTest').disabled = false;
+ };
return testLoop;
}
@@ -525,9 +505,8 @@
currentCommandRow++;
var commandName = getCellText(currentCommandRow, 0);
- var target = replaceVariables(getCellText(currentCommandRow, 1));
- var value = replaceVariables(getCellText(currentCommandRow, 2));
-
+ var target = getCellText(currentCommandRow, 1);
+ var value = getCellText(currentCommandRow, 2);
var command = new SeleniumCommand(commandName, target, removeNbsp(value));
return command;
@@ -538,21 +517,23 @@
return value.replace(/\240/g, "");
}
-function focusOnElement(element) {
- if (element.focus) {
- element.focus();
+function scrollIntoView(element) {
+ if (element.scrollIntoView) {
+ element.scrollIntoView();
return;
}
+
+ // For Konqueror, we have to create a remove an element.
var anchor = element.ownerDocument.createElement("a");
anchor.innerHTML = "!CURSOR!";
element.appendChild(anchor, element);
- anchor.focus();
+// anchor.focus();
element.removeChild(anchor);
}
function commandStarted() {
inputTableRows[currentCommandRow].bgColor = workingColor;
- focusOnElement(inputTableRows[currentCommandRow].cells[0]);
+ scrollIntoView(inputTableRows[currentCommandRow].cells[0]);
printMetrics();
}
@@ -619,38 +600,4 @@
Selenium.prototype.doPause = function(waitTime) {
selenium.callOnNextPageLoad(null);
testLoop.pauseInterval = waitTime;
-};
-
-// Store the value of a form input in a variable
-Selenium.prototype.doStoreValue = function(target, varName) {
- if (!varName) {
- // Backward compatibility mode: read the ENTIRE text of the page
- // and stores it in a variable with the name of the target
- value = this.page().bodyText();
- storedVars[target] = value;
- return;
- }
- var element = this.page().findElement(target);
- storedVars[varName] = getInputValue(element);
-};
-
-// Store the text of an element in a variable
-Selenium.prototype.doStoreText = function(target, varName) {
- var element = this.page().findElement(target);
- storedVars[varName] = getText(element);
-};
-
-Selenium.prototype.doSetVariable = function(varName, variableExpression) {
- var value = eval(variableExpression);
- storedVars[varName] = value;
-};
-
-Selenium.prototype.doClickWithOptionalWait = function(target, wait) {
-
- this.doClick(target);
-
- if(wait != "nowait") {
- return SELENIUM_PROCESS_WAIT;
- }
-
-};
+};
\ No newline at end of file
=== Products/Zelenium/selenium/selenium-logging.js 1.2 => 1.3 ===
--- Products/Zelenium/selenium/selenium-logging.js:1.2 Fri May 6 07:46:12 2005
+++ Products/Zelenium/selenium/selenium-logging.js Tue Jun 7 13:17:46 2005
@@ -1 +1,88 @@
-/*
* 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 LEVEL_DEBUG = 0;
var LEVEL_INFO = 1;
var LEVEL_WARN = 2;
var LEVEL_ERROR = 3;
function Logger(logLevel) {
this.level = logLevel;
this.logConsole = document.getElementById('logging-console');
this.logList = document.getElementById('log-list');
this.hide();
}
Logger.prototype.show = function() {
this.logConsole.style.display = "";
};
Logger.prototype.hide = function() {
this.logConsole.style.display = "none";
};
Logger.prototype.clear = function() {
while (this.logList.hasChildNodes()) {
this.logList.removeChild(this.logList.firstChild);
}
};
Logger.prototype.debug = function(message) {
if (this.level <= LEVEL_DEBUG) {
this.log(message, "debug");
}
};
Logger.prototype.info = function(message) {
if (this.level <= LEVEL_INFO) {
this.log(message, "info");
}
};
Logger.prototype.warn = function(message) {
if (this.level <= LEVEL_WARN) {
this.log(message, "warn");
}
};
Logger.prototype.error = function(message) {
if (this.level <= LEVEL_ERROR) {
this.log(message, "error");
}
};
Logger.prototype.log = function(message, className) {
var loggingNode = document.createElement('li');
loggingNode.className = className;
loggingNode.appendChild(document.createTextNode(message));
this.logList.appendChild(loggingNode);
this.show();
};
\ No newline at end of file
+/*
+* 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 LEVEL_DEBUG = 0;
+var LEVEL_INFO = 1;
+var LEVEL_WARN = 2;
+var LEVEL_ERROR = 3;
+
+function Logger(logLevel) {
+ this.level = logLevel;
+ this.logConsole = document.getElementById('logging-console');
+ this.logList = document.getElementById('log-list');
+ this.hide();
+}
+
+Logger.prototype.show = function() {
+ this.logConsole.style.display = "";
+};
+
+Logger.prototype.hide = function() {
+ this.logConsole.style.display = "none";
+};
+
+Logger.prototype.clear = function() {
+ while (this.logList.hasChildNodes()) {
+ this.logList.removeChild(this.logList.firstChild);
+ }
+};
+
+Logger.prototype.debug = function(message) {
+ if (this.level <= LEVEL_DEBUG) {
+ this.log(message, "debug");
+ }
+};
+
+Logger.prototype.info = function(message) {
+ if (this.level <= LEVEL_INFO) {
+ this.log(message, "info");
+ }
+};
+
+Logger.prototype.warn = function(message) {
+ if (this.level <= LEVEL_WARN) {
+ this.log(message, "warn");
+ }
+};
+
+Logger.prototype.error = function(message) {
+ if (this.level <= LEVEL_ERROR) {
+ this.log(message, "error");
+ }
+};
+
+Logger.prototype.log = function(message, className) {
+ var loggingNode = document.createElement('li');
+ loggingNode.className = className;
+ loggingNode.appendChild(document.createTextNode(message));
+
+ this.logList.appendChild(loggingNode);
+ this.show();
+};
+
+function noop() {};
+
+function DummyLogger() {
+};
+
+DummyLogger.prototype.show = noop;
+DummyLogger.prototype.hide = noop;
+DummyLogger.prototype.clear = noop;
+DummyLogger.prototype.log = noop;
+DummyLogger.prototype.debug = noop;
+DummyLogger.prototype.info = noop;
+DummyLogger.prototype.warn = noop;
+DummyLogger.prototype.error = noop;
\ No newline at end of file
More information about the Zope-CVS
mailing list