Commit 241f53da 241f53dad11711f4ac38ce189e5d5c2ad3a2626b by Nicolas Perriault

thou can haz XPath selectors - refs #54

1 parent dd84d1ab
...@@ -242,15 +242,15 @@ ...@@ -242,15 +242,15 @@
242 * @return NodeList|undefined 242 * @return NodeList|undefined
243 */ 243 */
244 this.findAll = function findAll(selector) { 244 this.findAll = function findAll(selector) {
245 var pSelector = this.processSelector(selector);
246 try { 245 try {
246 var pSelector = this.processSelector(selector);
247 if (pSelector.type === 'xpath') { 247 if (pSelector.type === 'xpath') {
248 return this.getElementsByXPath(pSelector.path); 248 return this.getElementsByXPath(pSelector.path);
249 } else { 249 } else {
250 return document.querySelectorAll(pSelector.path); 250 return document.querySelectorAll(pSelector.path);
251 } 251 }
252 } catch (e) { 252 } catch (e) {
253 this.log('findAll(): invalid selector provided "' + pSelector.toString() + '":' + e, "error"); 253 this.log('findAll(): invalid selector provided "' + selector + '":' + e, "error");
254 } 254 }
255 }; 255 };
256 256
...@@ -261,15 +261,15 @@ ...@@ -261,15 +261,15 @@
261 * @return HTMLElement|undefined 261 * @return HTMLElement|undefined
262 */ 262 */
263 this.findOne = function findOne(selector) { 263 this.findOne = function findOne(selector) {
264 var pSelector = this.processSelector(selector);
265 try { 264 try {
265 var pSelector = this.processSelector(selector);
266 if (pSelector.type === 'xpath') { 266 if (pSelector.type === 'xpath') {
267 return this.getElementByXPath(pSelector.path); 267 return this.getElementByXPath(pSelector.path);
268 } else { 268 } else {
269 return document.querySelector(pSelector.path); 269 return document.querySelector(pSelector.path);
270 } 270 }
271 } catch (e) { 271 } catch (e) {
272 this.log('findOne(): invalid selector provided "' + selector + '":' + e, "errors"); 272 this.log('findOne(): invalid selector provided "' + selector + '":' + e, "error");
273 } 273 }
274 }; 274 };
275 275
...@@ -351,6 +351,12 @@ ...@@ -351,6 +351,12 @@
351 } 351 }
352 }; 352 };
353 353
354 /**
355 * Retrieves a single DOM element mathcing a given XPath expression.
356 *
357 * @param String expression The XPath expression
358 * @return HTMLElement or null
359 */
354 this.getElementByXPath = function getElementByXPath(expression) { 360 this.getElementByXPath = function getElementByXPath(expression) {
355 var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 361 var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
356 if (a.snapshotLength > 0) { 362 if (a.snapshotLength > 0) {
...@@ -358,6 +364,12 @@ ...@@ -358,6 +364,12 @@
358 } 364 }
359 }; 365 };
360 366
367 /**
368 * Retrieves all DOM elements matching a given XPath expression.
369 *
370 * @param String expression The XPath expression
371 * @return Array
372 */
361 this.getElementsByXPath = function getElementsByXPath(expression) { 373 this.getElementsByXPath = function getElementsByXPath(expression) {
362 var nodes = []; 374 var nodes = [];
363 var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); 375 var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
...@@ -367,6 +379,12 @@ ...@@ -367,6 +379,12 @@
367 return nodes; 379 return nodes;
368 }; 380 };
369 381
382 /**
383 * Removed all DOM elements matching a given XPath expression.
384 *
385 * @param String expression The XPath expression
386 * @return Array
387 */
370 this.removeElementsByXPath = function removeElementsByXPath(expression) { 388 this.removeElementsByXPath = function removeElementsByXPath(expression) {
371 var a = document.evaluate(expression, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); 389 var a = document.evaluate(expression, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
372 for (var i = 0; i < a.snapshotLength; i++) { 390 for (var i = 0; i < a.snapshotLength; i++) {
...@@ -385,6 +403,20 @@ ...@@ -385,6 +403,20 @@
385 console.log("[casper:" + (level || "debug") + "] " + message); 403 console.log("[casper:" + (level || "debug") + "] " + message);
386 }; 404 };
387 405
406 /**
407 * Processes a selector input, either as a string or an object.
408 *
409 * If passed an object, if must be of the form:
410 *
411 * selectorObject = {
412 * type: <'css' or 'xpath'>,
413 * path: <a string>
414 * }
415 *
416 * @param String|Object selector The selector string or object
417 *
418 * @return an object containing 'type' and 'path' keys
419 */
388 this.processSelector = function processSelector(selector) { 420 this.processSelector = function processSelector(selector) {
389 var selectorObject = { 421 var selectorObject = {
390 toString: function toString() { 422 toString: function toString() {
......
...@@ -141,7 +141,7 @@ var Tester = function Tester(casper, options) { ...@@ -141,7 +141,7 @@ var Tester = function Tester(casper, options) {
141 } 141 }
142 }); 142 });
143 }; 143 };
144 144
145 /** 145 /**
146 * Asserts that two values are strictly not equals. 146 * Asserts that two values are strictly not equals.
147 * 147 *
...@@ -149,7 +149,7 @@ var Tester = function Tester(casper, options) { ...@@ -149,7 +149,7 @@ var Tester = function Tester(casper, options) {
149 * @param Mixed expected The unwanted value 149 * @param Mixed expected The unwanted value
150 * @param String message Test description 150 * @param String message Test description
151 */ 151 */
152 152
153 this.assertNotEquals = function assertNotEquals(subject, shouldnt, message) { 153 this.assertNotEquals = function assertNotEquals(subject, shouldnt, message) {
154 var eventName; 154 var eventName;
155 message = message || ""; 155 message = message || "";
...@@ -212,6 +212,10 @@ var Tester = function Tester(casper, options) { ...@@ -212,6 +212,10 @@ var Tester = function Tester(casper, options) {
212 return this.assert(casper.exists(selector), message); 212 return this.assert(casper.exists(selector), message);
213 }; 213 };
214 214
215 this.assertDoesntExist = this.assertNotExists = function assertDoesntExist(selector, message) {
216 return this.assertNot(casper.exists(selector), message);
217 };
218
215 /** 219 /**
216 * Asserts that current HTTP status is the one passed as argument. 220 * Asserts that current HTTP status is the one passed as argument.
217 * 221 *
......
...@@ -20,4 +20,19 @@ for (var what in testCases) { ...@@ -20,4 +20,19 @@ for (var what in testCases) {
20 casper.test.assertEquals(clientutils.decode(encoded), source, 'ClientUtils can encode and decode ' + what); 20 casper.test.assertEquals(clientutils.decode(encoded), source, 'ClientUtils can encode and decode ' + what);
21 } 21 }
22 22
23 casper.test.done(); 23 casper.test.comment('XPath');
24
25 casper.start('tests/site/index.html', function() {
26 this.test.assertExists({
27 type: 'xpath',
28 path: '/html/body/ul/li[2]'
29 }, 'XPath selector can find an element');
30 this.test.assertDoesntExist({
31 type: 'xpath',
32 path: '/html/body/ol/li[2]'
33 }, 'XPath selector does not retrieve an unexistent element');
34 });
35
36 casper.run(function() {
37 this.test.done();
38 });
......