Commit 241f53da 241f53dad11711f4ac38ce189e5d5c2ad3a2626b by Nicolas Perriault

thou can haz XPath selectors - refs #54

1 parent dd84d1ab
......@@ -242,15 +242,15 @@
* @return NodeList|undefined
*/
this.findAll = function findAll(selector) {
var pSelector = this.processSelector(selector);
try {
var pSelector = this.processSelector(selector);
if (pSelector.type === 'xpath') {
return this.getElementsByXPath(pSelector.path);
} else {
return document.querySelectorAll(pSelector.path);
}
} catch (e) {
this.log('findAll(): invalid selector provided "' + pSelector.toString() + '":' + e, "error");
this.log('findAll(): invalid selector provided "' + selector + '":' + e, "error");
}
};
......@@ -261,15 +261,15 @@
* @return HTMLElement|undefined
*/
this.findOne = function findOne(selector) {
var pSelector = this.processSelector(selector);
try {
var pSelector = this.processSelector(selector);
if (pSelector.type === 'xpath') {
return this.getElementByXPath(pSelector.path);
} else {
return document.querySelector(pSelector.path);
}
} catch (e) {
this.log('findOne(): invalid selector provided "' + selector + '":' + e, "errors");
this.log('findOne(): invalid selector provided "' + selector + '":' + e, "error");
}
};
......@@ -351,6 +351,12 @@
}
};
/**
* Retrieves a single DOM element mathcing a given XPath expression.
*
* @param String expression The XPath expression
* @return HTMLElement or null
*/
this.getElementByXPath = function getElementByXPath(expression) {
var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (a.snapshotLength > 0) {
......@@ -358,6 +364,12 @@
}
};
/**
* Retrieves all DOM elements matching a given XPath expression.
*
* @param String expression The XPath expression
* @return Array
*/
this.getElementsByXPath = function getElementsByXPath(expression) {
var nodes = [];
var a = document.evaluate(expression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
......@@ -367,6 +379,12 @@
return nodes;
};
/**
* Removed all DOM elements matching a given XPath expression.
*
* @param String expression The XPath expression
* @return Array
*/
this.removeElementsByXPath = function removeElementsByXPath(expression) {
var a = document.evaluate(expression, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < a.snapshotLength; i++) {
......@@ -385,6 +403,20 @@
console.log("[casper:" + (level || "debug") + "] " + message);
};
/**
* Processes a selector input, either as a string or an object.
*
* If passed an object, if must be of the form:
*
* selectorObject = {
* type: <'css' or 'xpath'>,
* path: <a string>
* }
*
* @param String|Object selector The selector string or object
*
* @return an object containing 'type' and 'path' keys
*/
this.processSelector = function processSelector(selector) {
var selectorObject = {
toString: function toString() {
......
......@@ -212,6 +212,10 @@ var Tester = function Tester(casper, options) {
return this.assert(casper.exists(selector), message);
};
this.assertDoesntExist = this.assertNotExists = function assertDoesntExist(selector, message) {
return this.assertNot(casper.exists(selector), message);
};
/**
* Asserts that current HTTP status is the one passed as argument.
*
......
......@@ -20,4 +20,19 @@ for (var what in testCases) {
casper.test.assertEquals(clientutils.decode(encoded), source, 'ClientUtils can encode and decode ' + what);
}
casper.test.done();
casper.test.comment('XPath');
casper.start('tests/site/index.html', function() {
this.test.assertExists({
type: 'xpath',
path: '/html/body/ul/li[2]'
}, 'XPath selector can find an element');
this.test.assertDoesntExist({
type: 'xpath',
path: '/html/body/ol/li[2]'
}, 'XPath selector does not retrieve an unexistent element');
});
casper.run(function() {
this.test.done();
});
......