selenium-webdriver 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
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
  /**