3 * Adds a xml_eq method to AnotherWay test objects.
10 * Function: createNode
11 * Given a string, try to create an XML DOM node. Throws string messages
15 * text - {String} An XML string.
18 * {DOMElement} An element node.
20 function createNode(text) {
22 var index = text.indexOf('<');
24 text = text.substring(index);
28 if(window.ActiveXObject && !this.xmldom) {
29 doc = new ActiveXObject("Microsoft.XMLDOM");
33 throw "ActiveXObject loadXML failed: " + err;
35 } else if(window.DOMParser) {
37 doc = new DOMParser().parseFromString(text, 'text/xml');
39 throw "DOMParser.parseFromString failed";
41 if(doc.documentElement && doc.documentElement.nodeName == "parsererror") {
42 throw "DOMParser.parseFromString returned parsererror";
45 var req = new XMLHttpRequest();
46 req.open("GET", "data:text/xml;charset=utf-8," +
47 encodeURIComponent(text), false);
48 if(req.overrideMimeType) {
49 req.overrideMimeType("text/xml");
52 doc = req.responseXML;
55 var root = doc.documentElement;
57 throw "no documentElement";
63 * Function assertEqual
64 * Test two objects for equivalence (based on ==). Throw an exception
70 * msg - {String} The message to be thrown. This message will be appended
71 * with ": got {got} but expected {expected}" where got and expected are
72 * replaced with string representations of the above arguments.
74 function assertEqual(got, expected, msg) {
75 if(got === undefined) {
77 } else if (got === null) {
80 if(expected === undefined) {
81 expected = "undefined";
82 } else if (expected === null) {
86 throw msg + ": got '" + got + "' but expected '" + expected + "'";
91 * Function assertElementNodesEqual
92 * Test two element nodes for equivalence. Nodes are considered equivalent
93 * if they are of the same type, have the same name, have the same
94 * namespace prefix and uri, and if all child nodes are equivalent.
95 * Throws a message as exception if not equivalent.
99 * expected - {DOMElement}
100 * options - {Object} Optional object for configuring test options.
103 * prefix - {Boolean} Compare element and attribute
104 * prefixes (namespace uri always tested). Default is false.
105 * includeWhiteSpace - {Boolean} Include whitespace only nodes when
106 * comparing child nodes. Default is false.
108 function assertElementNodesEqual(got, expected, options) {
109 var testPrefix = (options && options.prefix === true);
112 assertEqual(got.nodeType, expected.nodeType, "Node type mismatch");
115 var gotName = testPrefix ?
116 got.nodeName : got.nodeName.split(":").pop();
117 var expName = testPrefix ?
118 expected.nodeName : expected.nodeName.split(":").pop();
119 assertEqual(gotName, expName, "Node name mismatch");
121 // for text nodes compare value
122 if(got.nodeType == 3) {
124 got.nodeValue, expected.nodeValue, "Node value mismatch"
127 // for element type nodes compare namespace, attributes, and children
128 else if(got.nodeType == 1) {
130 // test namespace alias and uri
131 if(got.prefix || expected.prefix) {
134 got.prefix, expected.prefix,
135 "Bad prefix for " + got.nodeName
139 if(got.namespaceURI || expected.namespaceURI) {
141 got.namespaceURI, expected.namespaceURI,
142 "Bad namespaceURI for " + got.nodeName
146 // compare attributes - disregard xmlns given namespace handling above
152 for(var i=0; i<got.attributes.length; ++i) {
153 ga = got.attributes[i];
154 if(ga.specified === undefined || ga.specified === true) {
155 if(ga.name.split(":").shift() != "xmlns") {
156 gn = testPrefix ? ga.name : ga.name.split(":").pop();
162 for(var i=0; i<expected.attributes.length; ++i) {
163 ea = expected.attributes[i];
164 if(ea.specified === undefined || ea.specified === true) {
165 if(ea.name.split(":").shift() != "xmlns") {
166 en = testPrefix ? ea.name : ea.name.split(":").pop();
173 gotAttrLen, expAttrLen,
174 "Attributes length mismatch for " + got.nodeName
177 for(var name in gotAttr) {
178 if(expAttr[name] == undefined) {
179 throw "Attribute name " + gotAttr[name].name + " expected for element " + got.nodeName;
181 // test attribute namespace
183 gotAttr[name].namespaceURI, expAttr[name].namespaceURI,
184 "Attribute namespace mismatch for element " +
185 got.nodeName + " attribute name " + gotAttr[name].name
187 // test attribute value
189 gotAttr[name].value, expAttr[name].value,
190 "Attribute value mismatch for element " + got.nodeName +
191 " attribute name " + gotAttr[name].name
196 var gotChildNodes = getChildNodes(got, options);
197 var expChildNodes = getChildNodes(expected, options);
200 gotChildNodes.length, expChildNodes.length,
201 "Children length mismatch for " + got.nodeName
203 for(var j=0; j<gotChildNodes.length; ++j) {
205 assertElementNodesEqual(
206 gotChildNodes[j], expChildNodes[j], options
209 throw "Bad child " + j + " for element " + got.nodeName + ": " + err;
217 * Function getChildNodes
218 * Returns the child nodes of the specified nodes. By default this method
219 * will ignore child text nodes which are made up of whitespace content.
220 * The 'includeWhiteSpace' option is used to control this behaviour.
223 * node - {DOMElement}
224 * options - {Object} Optional object for test configuration.
227 * includeWhiteSpace - {Boolean} Include whitespace only nodes when
228 * comparing child nodes. Default is false.
231 * {Array} of {DOMElement}
233 function getChildNodes(node, options) {
235 if (options && options.includeWhiteSpace) {
236 return node.childNodes;
240 for (var i = 0; i < node.childNodes.length; i++ ) {
241 var child = node.childNodes[i];
242 if (child.nodeType == 1) {
243 //element node, add it
246 else if (child.nodeType == 3) {
247 //text node, add if non empty
248 if (child.nodeValue &&
249 child.nodeValue.replace(/^\s*(.*?)\s*$/, "$1") != "" ) {
261 * Function: Test.AnotherWay._test_object_t.xml_eq
262 * Test if two XML nodes are equivalent. Tests for same node types, same
263 * node names, same namespace URI, same attributes, and recursively
264 * tests child nodes for same criteria.
267 * t.xml_eq(got, expected, message);
271 * got - {DOMElement | String} A DOM node or XML string to test.
272 * expected - {DOMElement | String} The expected DOM node or XML string.
273 * msg - {String} A message to print with test output.
274 * options - {Object} Optional object for configuring test.
277 * prefix - {Boolean} Compare element and attribute
278 * prefixes (namespace uri always tested). Default is false.
279 * includeWhiteSpace - {Boolean} Include whitespace only nodes when
280 * comparing child nodes. Default is false.
282 var proto = Test.AnotherWay._test_object_t.prototype;
283 proto.xml_eq = function(got, expected, msg, options) {
284 // convert arguments to nodes if string
285 if(typeof got == "string") {
287 got = createNode(got);
289 this.fail(msg + ": got argument could not be converted to an XML node: " + err);
293 if(typeof expected == "string") {
295 expected = createNode(expected);
297 this.fail(msg + ": expected argument could not be converted to an XML node: " + err);
302 // test nodes for equivalence
304 assertElementNodesEqual(got, expected, options);
307 this.fail(msg + ": " + err);