selenium-webdriver 0.0.14 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. data/chrome/src/rb/lib/selenium/webdriver/chrome/bridge.rb +12 -0
  2. data/chrome/src/rb/lib/selenium/webdriver/chrome/command_executor.rb +5 -1
  3. data/common/src/js/core/scripts/htmlutils.js +404 -76
  4. data/common/src/js/core/scripts/rpc-optimizing-user-extension.js +5206 -0
  5. data/common/src/js/core/scripts/selenium-api.js +10 -15
  6. data/common/src/js/core/scripts/selenium-browserbot.js +26 -21
  7. data/common/src/rb/lib/selenium/webdriver/child_process.rb +62 -8
  8. data/common/src/rb/lib/selenium/webdriver/find.rb +12 -11
  9. data/common/src/rb/lib/selenium/webdriver/platform.rb +34 -36
  10. data/common/src/rb/lib/selenium/webdriver/target_locator.rb +8 -0
  11. data/firefox/prebuilt/linux/Release/libwebdriver-firefox.so +0 -0
  12. data/firefox/src/extension/components/badCertListener.js +121 -19
  13. data/firefox/src/extension/components/screenshooter.js +1 -1
  14. data/firefox/src/extension/components/utils.js +19 -10
  15. data/firefox/src/extension/components/wrappedElement.js +8 -8
  16. data/firefox/src/rb/lib/selenium/webdriver/firefox.rb +8 -1
  17. data/firefox/src/rb/lib/selenium/webdriver/firefox/binary.rb +1 -1
  18. data/firefox/src/rb/lib/selenium/webdriver/firefox/bridge.rb +12 -0
  19. data/firefox/src/rb/lib/selenium/webdriver/firefox/extension_connection.rb +1 -1
  20. data/firefox/src/rb/lib/selenium/webdriver/firefox/launcher.rb +4 -0
  21. data/firefox/src/rb/lib/selenium/webdriver/firefox/profile.rb +18 -9
  22. data/jobbie/prebuilt/Win32/Release/InternetExplorerDriver.dll +0 -0
  23. data/jobbie/prebuilt/x64/Release/InternetExplorerDriver.dll +0 -0
  24. data/jobbie/src/rb/lib/selenium/webdriver/ie/bridge.rb +4 -0
  25. data/jobbie/src/rb/lib/selenium/webdriver/ie/util.rb +3 -2
  26. data/remote/client/src/rb/lib/selenium/webdriver/remote/bridge.rb +4 -0
  27. data/remote/client/src/rb/lib/selenium/webdriver/remote/default_http_client.rb +1 -1
  28. metadata +3 -2
@@ -54,6 +54,10 @@ module Selenium
54
54
  :name => id
55
55
  end
56
56
 
57
+ def switchToDefaultContent
58
+ execute :request => "switchToDefaultContent"
59
+ end
60
+
57
61
  def quit
58
62
  begin
59
63
  execute :request => 'quit'
@@ -177,6 +181,14 @@ module Selenium
177
181
  find_elements_by 'xpath', xpath, parent
178
182
  end
179
183
 
184
+ def findElementByCssSelector(parent, selector)
185
+ find_element_by 'css selector', selector, parent
186
+ end
187
+
188
+ def findElementsByCssSelector(parent, selector)
189
+ find_elements_by 'css selector', selector, parent
190
+ end
191
+
180
192
 
181
193
  #
182
194
  # Element functions
@@ -6,7 +6,7 @@ module Selenium
6
6
  JSON_TEMPLATE = "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n%s"
7
7
 
8
8
  def initialize
9
- @server = TCPServer.new("0.0.0.0", 0)
9
+ @server = TCPServer.new(localhost, 0)
10
10
  @queue = Queue.new
11
11
 
12
12
  @accepted_any = false
@@ -49,6 +49,10 @@ module Selenium
49
49
 
50
50
  private
51
51
 
52
+ def localhost
53
+ Platform.ironruby? ? "localhost" : "0.0.0.0" # yeah, weird..
54
+ end
55
+
52
56
  def start_run_loop
53
57
  while(@listening) do
54
58
  socket = @server.accept
@@ -1072,6 +1072,394 @@ function parse_locator(locator)
1072
1072
  return { type: 'implicit', string: locator };
1073
1073
  }
1074
1074
 
1075
+ /**
1076
+ * An interface definition for XPath engine implementations; an instance of
1077
+ * XPathEngine should be their prototype. Sub-implementations need only define
1078
+ * overrides of the methods provided here.
1079
+ */
1080
+ function XPathEngine() {
1081
+ // public
1082
+ this.doc = null;
1083
+
1084
+ /**
1085
+ * Returns whether the current runtime environment supports the use of this
1086
+ * engine. Needs override.
1087
+ */
1088
+ this.isAvailable = function() { return false; };
1089
+
1090
+ /**
1091
+ * Sets the document to be used for evaluation. Always returns the current
1092
+ * engine object so as to be chainable.
1093
+ */
1094
+ this.setDocument = function(newDocument) {
1095
+ this.doc = newDocument;
1096
+ return this;
1097
+ };
1098
+
1099
+ /**
1100
+ * Returns a possibly-empty list of nodes. Needs override.
1101
+ */
1102
+ this.selectNodes = function(xpath, contextNode, namespaceResolver) {
1103
+ return [];
1104
+ };
1105
+
1106
+ /**
1107
+ * Returns a single node, or null if no nodes were selected. This default
1108
+ * implementation simply returns the first result of selectNodes(), or
1109
+ * null.
1110
+ */
1111
+ this.selectSingleNode = function(xpath, contextNode, namespaceResolver) {
1112
+ var nodes = this.selectNodes(xpath, contextNode, namespaceResolver);
1113
+ return (nodes.length > 0 ? nodes[0] : null);
1114
+ };
1115
+
1116
+ /**
1117
+ * Returns the number of matching nodes. This default implementation simply
1118
+ * returns the length of the result of selectNodes(), which should be
1119
+ * adequate for most sub-implementations.
1120
+ */
1121
+ this.countNodes = function(xpath, contextNode, namespaceResolver) {
1122
+ return this.selectNodes(xpath, contextNode, namespaceResolver).length;
1123
+ };
1124
+
1125
+ /**
1126
+ * An optimization; likely to be a no-op for many implementations. Always
1127
+ * returns the current engine object so as to be chainable.
1128
+ */
1129
+ this.setIgnoreAttributesWithoutValue = function(ignore) { return this; };
1130
+ }
1131
+
1132
+ /**
1133
+ * Implements XPathEngine.
1134
+ */
1135
+ function NativeEngine() {
1136
+ // public
1137
+ // Override
1138
+ this.isAvailable = function() {
1139
+ if (browserVersion && browserVersion.isIE) {
1140
+ // javascript-xpath can fake out the check otherwise
1141
+ return false;
1142
+ }
1143
+
1144
+ return this.doc && this.doc.evaluate;
1145
+ };
1146
+
1147
+ // Override
1148
+ this.selectNodes = function(xpath, contextNode, namespaceResolver) {
1149
+ if (contextNode != this.doc) {
1150
+ xpath = '.' + xpath;
1151
+ }
1152
+
1153
+ var nodes = [];
1154
+
1155
+ try {
1156
+ var xpathResult = this.doc.evaluate(xpath, contextNode,
1157
+ namespaceResolver, 0, null);
1158
+ }
1159
+ catch (e) {
1160
+ var msg = extractExceptionMessage(e);
1161
+ throw new SeleniumError("Invalid xpath [1]: " + msg);
1162
+ }
1163
+ finally {
1164
+ if (xpathResult == null) {
1165
+ // If the result is null, we should still throw an Error.
1166
+ throw new SeleniumError("Invalid xpath [2]: " + xpath);
1167
+ }
1168
+ }
1169
+
1170
+ var node = xpathResult.iterateNext();
1171
+
1172
+ while (node) {
1173
+ nodes.push(node);
1174
+ node = xpathResult.iterateNext();
1175
+ }
1176
+
1177
+ return nodes;
1178
+ };
1179
+ }
1180
+
1181
+ NativeEngine.prototype = new XPathEngine();
1182
+
1183
+ /**
1184
+ * Implements XPathEngine.
1185
+ */
1186
+ function AjaxsltEngine() {
1187
+ // private
1188
+ var ignoreAttributesWithoutValue = false;
1189
+
1190
+ function selectLogic(xpath, contextNode, namespaceResolver, firstMatch) {
1191
+ // DGF set xpathdebug = true (using getEval, if you like) to turn on JS
1192
+ // XPath debugging
1193
+ //xpathdebug = true;
1194
+ var context;
1195
+
1196
+ if (contextNode == this.doc) {
1197
+ context = new ExprContext(this.doc);
1198
+ }
1199
+ else {
1200
+ // provide false values to get the default constructor values
1201
+ context = new ExprContext(contextNode, false, false,
1202
+ contextNode.parentNode);
1203
+ }
1204
+
1205
+ context.setCaseInsensitive(true);
1206
+ context.setIgnoreAttributesWithoutValue(ignoreAttributesWithoutValue);
1207
+ context.setReturnOnFirstMatch(firstMatch);
1208
+
1209
+ try {
1210
+ var xpathObj = xpathParse(xpath);
1211
+ }
1212
+ catch (e) {
1213
+ var msg = extractExceptionMessage(e);
1214
+ throw new SeleniumError("Invalid xpath [3]: " + msg);
1215
+ }
1216
+
1217
+ var nodes = []
1218
+ var xpathResult = xpathObj.evaluate(context);
1219
+
1220
+ if (xpathResult && xpathResult.value) {
1221
+ for (var i = 0; i < xpathResult.value.length; ++i) {
1222
+ nodes.push(xpathResult.value[i]);
1223
+ }
1224
+ }
1225
+
1226
+ return nodes;
1227
+ }
1228
+
1229
+ // public
1230
+ // Override
1231
+ this.isAvailable = function() { return true; };
1232
+
1233
+ // Override
1234
+ this.selectNodes = function(xpath, contextNode, namespaceResolver) {
1235
+ return selectLogic(xpath, contextNode, namespaceResolver, false);
1236
+ };
1237
+
1238
+ // Override
1239
+ this.selectSingleNode = function(xpath, contextNode, namespaceResolver) {
1240
+ var nodes = selectLogic(xpath, contextNode, namespaceResolver, true);
1241
+ return (nodes.length > 0 ? nodes[0] : null);
1242
+ };
1243
+
1244
+ // Override
1245
+ this.setIgnoreAttributesWithoutValue = function(ignore) {
1246
+ ignoreAttributesWithoutValue = ignore;
1247
+ return this;
1248
+ };
1249
+ }
1250
+
1251
+ AjaxsltEngine.prototype = new XPathEngine();
1252
+
1253
+ /**
1254
+ * Implements XPathEngine.
1255
+ */
1256
+ function JavascriptXPathEngine() {
1257
+ // private
1258
+ var engineDoc = document;
1259
+
1260
+ // public
1261
+ // Override
1262
+ this.isAvailable = function() { return true; };
1263
+
1264
+ // Override
1265
+ this.selectNodes = function(xpath, contextNode, namespaceResolver) {
1266
+ if (contextNode != this.doc) {
1267
+ // Regarding use of the second argument to document.evaluate():
1268
+ // http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/a59ce20639c74ba1/a9d9f53e88e5ebb5
1269
+ xpath = '.' + xpath;
1270
+ }
1271
+
1272
+ var nodes = [];
1273
+
1274
+ try {
1275
+ // When using the new and faster javascript-xpath library, we'll
1276
+ // use the TestRunner's document object, not the App-Under-Test's
1277
+ // document. The new library only modifies the TestRunner document
1278
+ // with the new functionality.
1279
+ var xpathResult = engineDoc.evaluate(xpath, contextNode,
1280
+ namespaceResolver, 0, null);
1281
+ }
1282
+ catch (e) {
1283
+ var msg = extractExceptionMessage(e);
1284
+ throw new SeleniumError("Invalid xpath [1]: " + msg);
1285
+ }
1286
+ finally {
1287
+ if (xpathResult == null) {
1288
+ // If the result is null, we should still throw an Error.
1289
+ throw new SeleniumError("Invalid xpath [2]: " + xpath);
1290
+ }
1291
+ }
1292
+
1293
+ var node = xpathResult.iterateNext();
1294
+
1295
+ while (node) {
1296
+ nodes.push(node);
1297
+ node = xpathResult.iterateNext();
1298
+ }
1299
+
1300
+ return nodes;
1301
+ };
1302
+ }
1303
+
1304
+ JavascriptXPathEngine.prototype = new XPathEngine();
1305
+
1306
+ /**
1307
+ * An object responsible for handling XPath logic. New XPath engines can be
1308
+ * registered to this evaluator on the fly.
1309
+ *
1310
+ * @param newDefaultEngineName the name of the default XPath engine. Must be
1311
+ * a non-native engine that is always available.
1312
+ * Defaults to 'ajaxslt'.
1313
+ */
1314
+ function XPathEvaluator(newDefaultEngineName) {
1315
+ // private
1316
+ var nativeEngine = new NativeEngine();
1317
+ var defaultEngineName = newDefaultEngineName || 'ajaxslt';
1318
+ var engines = {
1319
+ 'ajaxslt' : new AjaxsltEngine(),
1320
+ 'javascript-xpath': new JavascriptXPathEngine(),
1321
+ 'native' : nativeEngine
1322
+ };
1323
+
1324
+ var currentEngineName = defaultEngineName;
1325
+ var allowNativeXPath = true;
1326
+ var ignoreAttributesWithoutValue = true;
1327
+
1328
+ function preprocess(xpath) {
1329
+ // Trim any trailing "/": not valid xpath, and remains from attribute
1330
+ // locator.
1331
+ if (xpath.charAt(xpath.length - 1) == '/') {
1332
+ xpath = xpath.slice(0, -1);
1333
+ }
1334
+ // HUGE hack - remove namespace from xpath for IE
1335
+ if (browserVersion && browserVersion.isIE) {
1336
+ xpath = xpath.replace(/x:/g, '')
1337
+ }
1338
+
1339
+ return xpath;
1340
+ }
1341
+
1342
+ /**
1343
+ * Returns the most sensible engine given the settings and the document
1344
+ * object.
1345
+ */
1346
+ function getEngineFor(inDocument) {
1347
+ if (allowNativeXPath &&
1348
+ nativeEngine.setDocument(inDocument).isAvailable()) {
1349
+ return nativeEngine;
1350
+ }
1351
+
1352
+ var currentEngine = engines[currentEngineName];
1353
+
1354
+ if (currentEngine &&
1355
+ currentEngine.setDocument(inDocument).isAvailable()) {
1356
+ return currentEngine;
1357
+ }
1358
+
1359
+ return engines[defaultEngineName].setDocument(inDocument);
1360
+ }
1361
+
1362
+ /**
1363
+ * Dispatches an XPath evaluation method on the relevant engine for the
1364
+ * given document, and returns the result
1365
+ */
1366
+ function dispatch(methodName, inDocument, xpath, contextNode, namespaceResolver) {
1367
+ xpath = preprocess(xpath);
1368
+
1369
+ if (! contextNode) {
1370
+ contextNode = inDocument;
1371
+ }
1372
+
1373
+ return getEngineFor(inDocument)
1374
+ .setIgnoreAttributesWithoutValue(ignoreAttributesWithoutValue)
1375
+ [methodName](xpath, contextNode, namespaceResolver);
1376
+ }
1377
+
1378
+ // public
1379
+ /**
1380
+ * Registers a new engine by name, and returns whether the registration was
1381
+ * successful. Each registered engine must be an instance of XPathEngine.
1382
+ * The engines registered by default - "ajaxslt", "javascript-xpath",
1383
+ * "native", and "default" - can't be overwritten.
1384
+ */
1385
+ this.registerEngine = function(name, engine) {
1386
+ // can't overwrite one of these
1387
+ if (name == 'ajaxslt' ||
1388
+ name == 'javascript-xpath' ||
1389
+ name == 'native' ||
1390
+ name == 'default') {
1391
+ return false;
1392
+ }
1393
+
1394
+ if (! (engine instanceof XPathEngine)) {
1395
+ return false;
1396
+ }
1397
+
1398
+ engines[name] = engine;
1399
+ return true;
1400
+ }
1401
+
1402
+ this.getRegisteredEngine = function(name) {
1403
+ return engines[name];
1404
+ };
1405
+
1406
+ this.setCurrentEngine = function(name) {
1407
+ if (name == 'default') {
1408
+ currentEngineName = defaultEngineName;
1409
+ }
1410
+ else if (! engines[name]) {
1411
+ return;
1412
+ }
1413
+ else {
1414
+ currentEngineName = name;
1415
+ }
1416
+ };
1417
+
1418
+ this.getCurrentEngine = function() {
1419
+ return currentEngineName || defaultEngineName;
1420
+ };
1421
+
1422
+ this.setAllowNativeXPath = function(allow) {
1423
+ allowNativeXPath = allow;
1424
+ }
1425
+
1426
+ this.isAllowNativeXPath = function() {
1427
+ return allowNativeXPath;
1428
+ }
1429
+
1430
+ this.setIgnoreAttributesWithoutValue = function(ignore) {
1431
+ ignoreAttributesWithoutValue = ignore;
1432
+ };
1433
+
1434
+ this.isIgnoreAttributesWithoutValue = function() {
1435
+ return ignoreAttributesWithoutValue;
1436
+ };
1437
+
1438
+ this.selectNodes = function(inDocument, xpath, contextNode, namespaceResolver) {
1439
+ return dispatch('selectNodes', inDocument, xpath, contextNode,
1440
+ namespaceResolver);
1441
+ };
1442
+
1443
+ this.selectSingleNode = function(inDocument, xpath, contextNode, namespaceResolver) {
1444
+ return dispatch('selectSingleNode', inDocument, xpath, contextNode,
1445
+ namespaceResolver);
1446
+ };
1447
+
1448
+ this.countNodes = function(inDocument, xpath, contextNode, namespaceResolver) {
1449
+ return dispatch('countNodes', inDocument, xpath, contextNode,
1450
+ namespaceResolver);
1451
+ };
1452
+
1453
+ // initialization
1454
+ this.init();
1455
+ };
1456
+
1457
+ /**
1458
+ * Gives the user an overridable hook for registering new XPath engines, for
1459
+ * example from user extensions.
1460
+ */
1461
+ XPathEvaluator.prototype.init = function() {};
1462
+
1075
1463
  /**
1076
1464
  * Evaluates an xpath on a document, and returns a list containing nodes in the
1077
1465
  * resulting nodeset. The browserbot xpath methods are now backed by this
@@ -1114,9 +1502,10 @@ function parse_locator(locator)
1114
1502
  */
1115
1503
  function eval_xpath(xpath, inDocument, opts)
1116
1504
  {
1117
- if (!opts) {
1505
+ if (! opts) {
1118
1506
  var opts = {};
1119
1507
  }
1508
+
1120
1509
  var contextNode = opts.contextNode
1121
1510
  ? opts.contextNode : inDocument;
1122
1511
  var namespaceResolver = opts.namespaceResolver
@@ -1130,87 +1519,26 @@ function eval_xpath(xpath, inDocument, opts)
1130
1519
  var returnOnFirstMatch = (opts.returnOnFirstMatch != undefined)
1131
1520
  ? opts.returnOnFirstMatch : false;
1132
1521
 
1133
- // Trim any trailing "/": not valid xpath, and remains from attribute
1134
- // locator.
1135
- if (xpath.charAt(xpath.length - 1) == '/') {
1136
- xpath = xpath.slice(0, -1);
1137
- }
1138
- // HUGE hack - remove namespace from xpath for IE
1139
- if (browserVersion && browserVersion.isIE) {
1140
- xpath = xpath.replace(/x:/g, '')
1522
+ if (! eval_xpath.xpathEvaluator) {
1523
+ eval_xpath.xpathEvaluator = new XPathEvaluator();
1141
1524
  }
1142
1525
 
1143
- var nativeXpathAvailable = inDocument.evaluate;
1144
- var useNativeXpath = allowNativeXpath && nativeXpathAvailable;
1145
- var useDocumentEvaluate = useNativeXpath;
1146
-
1147
- // When using the new and faster javascript-xpath library,
1148
- // we'll use the TestRunner's document object, not the App-Under-Test's document.
1149
- // The new library only modifies the TestRunner document with the new
1150
- // functionality.
1151
- if (xpathLibrary == 'javascript-xpath' && !useNativeXpath) {
1152
- documentForXpath = document;
1153
- useDocumentEvaluate = true;
1154
- } else {
1155
- documentForXpath = inDocument;
1156
- }
1157
- var results = [];
1526
+ var xpathEvaluator = eval_xpath.xpathEvaluator;
1158
1527
 
1159
- // this is either native xpath or javascript-xpath via TestRunner.evaluate
1160
- if (useDocumentEvaluate) {
1161
- try {
1162
- // Regarding use of the second argument to document.evaluate():
1163
- // http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/a59ce20639c74ba1/a9d9f53e88e5ebb5
1164
- var xpathResult = documentForXpath
1165
- .evaluate((contextNode == inDocument ? xpath : '.' + xpath),
1166
- contextNode, namespaceResolver, 0, null);
1167
- }
1168
- catch (e) {
1169
- throw new SeleniumError("Invalid xpath [1]: " + extractExceptionMessage(e));
1170
- }
1171
- finally{
1172
- if (xpathResult == null) {
1173
- // If the result is null, we should still throw an Error.
1174
- throw new SeleniumError("Invalid xpath [2]: " + xpath);
1175
- }
1176
- }
1177
- var result = xpathResult.iterateNext();
1178
- while (result) {
1179
- results.push(result);
1180
- result = xpathResult.iterateNext();
1181
- }
1182
- return results;
1183
- }
1184
-
1185
- // If not, fall back to slower JavaScript implementation
1186
- // DGF set xpathdebug = true (using getEval, if you like) to turn on JS XPath debugging
1187
- //xpathdebug = true;
1188
- var context;
1189
- if (contextNode == inDocument) {
1190
- context = new ExprContext(inDocument);
1528
+ xpathEvaluator.setCurrentEngine(xpathLibrary);
1529
+ xpathEvaluator.setAllowNativeXPath(allowNativeXpath);
1530
+ xpathEvaluator.setIgnoreAttributesWithoutValue(ignoreAttributesWithoutValue);
1531
+
1532
+ if (returnOnFirstMatch) {
1533
+ var result = xpathEvaluator.selectSingleNode(inDocument, xpath,
1534
+ contextNode, namespaceResolver);
1191
1535
  }
1192
1536
  else {
1193
- // provide false values to get the default constructor values
1194
- context = new ExprContext(contextNode, false, false,
1195
- contextNode.parentNode);
1196
- }
1197
- context.setCaseInsensitive(true);
1198
- context.setIgnoreAttributesWithoutValue(ignoreAttributesWithoutValue);
1199
- context.setReturnOnFirstMatch(returnOnFirstMatch);
1200
- var xpathObj;
1201
- try {
1202
- xpathObj = xpathParse(xpath);
1203
- }
1204
- catch (e) {
1205
- throw new SeleniumError("Invalid xpath [3]: " + extractExceptionMessage(e));
1537
+ var result = xpathEvaluator.selectNodes(inDocument, xpath, contextNode,
1538
+ namespaceResolver);
1206
1539
  }
1207
- var xpathResult = xpathObj.evaluate(context);
1208
- if (xpathResult && xpathResult.value) {
1209
- for (var i = 0; i < xpathResult.value.length; ++i) {
1210
- results.push(xpathResult.value[i]);
1211
- }
1212
- }
1213
- return results;
1540
+
1541
+ return result;
1214
1542
  }
1215
1543
 
1216
1544
  /**