diff --git a/test/xml/xpath.js b/test/xml/xpath.js index 24ab4432..fe545362 100644 --- a/test/xml/xpath.js +++ b/test/xml/xpath.js @@ -50,6 +50,8 @@ describe("xml/xpath", function () { this._name = name; } if (attributes) { + this._namespaceURI = attributes[""] || ""; + delete attributes[""]; this._attributes = Object.keys(attributes).map(function (attributeName) { var attributeNode = new Node(attributeName); attributeNode._type = gpf.xml.nodeType.attribute; @@ -87,14 +89,32 @@ describe("xml/xpath", function () { return new Node(name, attributes, children); } + var SVG_NAMESPACE = "http://www.w3.org/2000/svg"; var documentNode = node("", [ node("html", [ node("head", [ node("title", ["Sample page"]), - node("script", {src: "/gpf.js"}) + node("script", { + src: "/gpf.js", + language: "javascript" + }) ]), node("body", [ - + node("svg", { + "": SVG_NAMESPACE, + height: "100", + width: "100" + }, [ + node("circle", { + "": SVG_NAMESPACE, + cx: "50", + cy: "50", + r: "40", + stroke: "black", + "stroke-width": "3", + fill: "red" + }) + ]) ]) ]) ]); @@ -103,13 +123,41 @@ describe("xml/xpath", function () { headNode = htmlNode.getChildNodes()[0], scriptNode = headNode.getChildNodes()[1], srcAttrNode = scriptNode.getAttributes()[0], - bodyNode = htmlNode.getChildNodes()[1]; + languageAttrNode = scriptNode.getAttributes()[1], + bodyNode = htmlNode.getChildNodes()[1], + svgNode = bodyNode.getChildNodes()[0], + circleNode = svgNode.getChildNodes()[0]; describe("xml/xpath", function () { - describe("gpf.xml.xpath.select", function () { + describe("validation", function () { + function shouldFail (xpath) { + it("does not parse: " + xpath, function () { + var exceptionCaught; + try { + gpf.xml.xpath.parse(xpath); + } catch (e) { + exceptionCaught = e; + } + assert(exceptionCaught instanceof gpf.Error.InvalidXPathSyntax); + }); + } + + shouldFail("test"); + shouldFail("///test"); + shouldFail("..//test"); + shouldFail(".//test || .//test"); + }); + describe("gpf.xml.xpath.select", function () { function generateTests (xpath, checks) { - describe(xpath, function () { + var namespaces = checks.namespaces, + label = xpath; + if (namespaces) { + label += Object.keys(namespaces).reduce(function (result, prefix) { + return result + " " + prefix + "=\"" + namespaces[prefix] + "\""; + }, " (with") + ")"; + } + describe(label, function () { if (checks.xpath) { it("parses", function () { var parsed = gpf.xml.xpath.parse(xpath); @@ -119,19 +167,19 @@ describe("xml/xpath", function () { } if (checks.document) { it("executes on document", function () { - var nodes = gpf.xml.xpath.select(xpath, documentNode); + var nodes = gpf.xml.xpath.select(xpath, documentNode, namespaces); checks.document(nodes); }); } if (checks.html) { it("executes on ", function () { - var nodes = gpf.xml.xpath.select(xpath, htmlNode); + var nodes = gpf.xml.xpath.select(xpath, htmlNode, namespaces); checks.html(nodes); }); } if (checks.head) { it("executes on ", function () { - var nodes = gpf.xml.xpath.select(xpath, headNode); + var nodes = gpf.xml.xpath.select(xpath, headNode, namespaces); checks.head(nodes); }); } @@ -221,6 +269,76 @@ describe("xml/xpath", function () { html: is(srcAttrNode), head: is(srcAttrNode) }); + + generateTests("/html/head/script/@*", { + xpath: function (parsed) { + assert(parsed instanceof gpf.xml.xpath.Chain); + assert(parsed.getChildren().length === 4); + assert(parsed.getChildren()[0] instanceof gpf.xml.xpath.Sub); + }, + document: is([srcAttrNode, languageAttrNode]), + html: is([srcAttrNode, languageAttrNode]), + head: is([srcAttrNode, languageAttrNode]) + }); + + generateTests("//html/head | ./script/@src", { + xpath: function (parsed) { + assert(parsed instanceof gpf.xml.xpath.Concat); + assert(parsed.getChildren()[0] instanceof gpf.xml.xpath.Chain); + assert(parsed.getChildren()[1] instanceof gpf.xml.xpath.Chain); + }, + document: is(headNode), + html: is(headNode), + head: is([headNode, srcAttrNode]) + }); + + generateTests("//svg:svg", { + namespaces: { + svg: SVG_NAMESPACE + }, + xpath: function (parsed) { + assert(parsed instanceof gpf.xml.xpath.Deep); + }, + document: is(svgNode), + html: is(svgNode), + head: is(svgNode) + }); + + generateTests(".//svg:*", { + namespaces: { + svg: SVG_NAMESPACE + }, + xpath: function (parsed) { + assert(parsed instanceof gpf.xml.xpath.Deep); + }, + document: is([svgNode, circleNode]), + html: is([svgNode, circleNode]), + head: isEmpty + }); + + generateTests("//svg:*", { + namespaces: { + notSvg: SVG_NAMESPACE + }, + xpath: function (parsed) { + assert(parsed instanceof gpf.xml.xpath.Deep); + }, + document: isEmpty, + html: isEmpty, + head: isEmpty + }); + + generateTests("//unknown:*", { + namespaces: { + unknown: "not a known namespace" + }, + xpath: function (parsed) { + assert(parsed instanceof gpf.xml.xpath.Deep); + }, + document: isEmpty, + html: isEmpty, + head: isEmpty + }); }); }); });