]> dev.renevier.net Git - syp.git/blob - openlayers/tests/xml_eq.js
move templates to a specific directory
[syp.git] / openlayers / tests / xml_eq.js
1 /**
2  * File: xml_eq.js
3  * Adds a xml_eq method to AnotherWay test objects.
4  *
5  */
6
7 (function() {
8
9     /**
10      * Function: createNode
11      * Given a string, try to create an XML DOM node.  Throws string messages
12      *     on failure.
13      * 
14      * Parameters:
15      * text - {String} An XML string.
16      *
17      * Returns:
18      * {DOMElement} An element node.
19      */
20     function createNode(text) {
21         
22         var index = text.indexOf('<');
23         if(index > 0) {
24             text = text.substring(index);
25         }
26         
27         var doc;
28         if(window.ActiveXObject && !this.xmldom) {
29             doc = new ActiveXObject("Microsoft.XMLDOM");
30             try {
31                 doc.loadXML(text);
32             } catch(err) {
33                 throw "ActiveXObject loadXML failed: " + err;
34             }
35         } else if(window.DOMParser) {
36             try {
37                 doc = new DOMParser().parseFromString(text, 'text/xml');
38             } catch(err) {
39                 throw "DOMParser.parseFromString failed";
40             }
41             if(doc.documentElement && doc.documentElement.nodeName == "parsererror") {
42                 throw "DOMParser.parseFromString returned parsererror";
43             }
44         } else {
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");
50             }
51             req.send(null);
52             doc = req.responseXML;
53         }
54         
55         var root = doc.documentElement;
56         if(!root) {
57             throw "no documentElement";
58         }
59         return root;
60     }
61     
62     /**
63      * Function assertEqual
64      * Test two objects for equivalence (based on ==).  Throw an exception
65      *     if not equivalent.
66      * 
67      * Parameters:
68      * got - {Object}
69      * expected - {Object}
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.
73      */
74     function assertEqual(got, expected, msg) {
75         if(got === undefined) {
76             got = "undefined";
77         } else if (got === null) {
78             got = "null";
79         }
80         if(expected === undefined) {
81             expected = "undefined";
82         } else if (expected === null) {
83             expected = "null";
84         }
85         if(got != expected) {
86             throw msg + ": got '" + got + "' but expected '" + expected + "'";
87         }
88     }
89     
90     /**
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.
96      * 
97      * Parameters:
98      * got - {DOMElement}
99      * expected - {DOMElement}
100      * options - {Object} Optional object for configuring test options.
101      *
102      * Valid 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.
107      */
108     function assertElementNodesEqual(got, expected, options) {
109         var testPrefix = (options && options.prefix === true);
110         
111         // compare types
112         assertEqual(got.nodeType, expected.nodeType, "Node type mismatch");
113         
114         // compare names
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");
120         
121         // for text nodes compare value
122         if(got.nodeType == 3) {
123             assertEqual(
124                 got.nodeValue, expected.nodeValue, "Node value mismatch"
125             );
126         }
127         // for element type nodes compare namespace, attributes, and children
128         else if(got.nodeType == 1) {
129             
130             // test namespace alias and uri
131             if(got.prefix || expected.prefix) {
132                 if(testPrefix) {
133                     assertEqual(
134                         got.prefix, expected.prefix,
135                         "Bad prefix for " + got.nodeName
136                     );
137                 }
138             }
139             if(got.namespaceURI || expected.namespaceURI) {
140                 assertEqual(
141                     got.namespaceURI, expected.namespaceURI,
142                     "Bad namespaceURI for " + got.nodeName
143                 );
144             }
145             
146             // compare attributes - disregard xmlns given namespace handling above
147             var gotAttrLen = 0;
148             var gotAttr = {};
149             var expAttrLen = 0;
150             var expAttr = {};
151             var ga, ea, gn, en;
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();
157                         gotAttr[gn] = ga;
158                         ++gotAttrLen;
159                     }
160                 }
161             }
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();
167                         expAttr[en] = ea;
168                         ++expAttrLen;
169                     }
170                 }
171             }
172             assertEqual(
173                 gotAttrLen, expAttrLen,
174                 "Attributes length mismatch for " + got.nodeName
175             );
176             var gv, ev;
177             for(var name in gotAttr) {
178                 if(expAttr[name] == undefined) {
179                     throw "Attribute name " + gotAttr[name].name + " expected for element " + got.nodeName;
180                 }
181                 // test attribute namespace
182                 assertEqual(
183                     gotAttr[name].namespaceURI, expAttr[name].namespaceURI,
184                     "Attribute namespace mismatch for element " +
185                     got.nodeName + " attribute name " + gotAttr[name].name
186                 );
187                 // test attribute value
188                 assertEqual(
189                     gotAttr[name].value, expAttr[name].value,
190                     "Attribute value mismatch for element " + got.nodeName +
191                     " attribute name " + gotAttr[name].name
192                 );
193             }
194             
195             // compare children
196             var gotChildNodes = getChildNodes(got, options);
197             var expChildNodes = getChildNodes(expected, options);
198
199             assertEqual(
200                 gotChildNodes.length, expChildNodes.length,
201                 "Children length mismatch for " + got.nodeName
202             );
203             for(var j=0; j<gotChildNodes.length; ++j) {
204                 try {
205                     assertElementNodesEqual(
206                         gotChildNodes[j], expChildNodes[j], options
207                     );
208                 } catch(err) {
209                     throw "Bad child " + j + " for element " + got.nodeName + ": " + err;
210                 }
211             }
212         }
213         return true;
214     }
215
216     /**
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.
221      * 
222      * Parameters:
223      * node - {DOMElement}
224      * options - {Object} Optional object for test configuration.
225      * 
226      * Valid options:
227      * includeWhiteSpace - {Boolean} Include whitespace only nodes when
228      *     comparing child nodes.  Default is false.
229      * 
230      * Returns:
231      * {Array} of {DOMElement}
232      */
233     function getChildNodes(node, options) {
234         //check whitespace
235         if (options && options.includeWhiteSpace) {
236             return node.childNodes;
237         }
238         else {
239            nodes = [];
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 
244                  nodes.push(child);
245               }
246               else if (child.nodeType == 3) {
247                  //text node, add if non empty
248                  if (child.nodeValue && 
249                        child.nodeValue.replace(/^\s*(.*?)\s*$/, "$1") != "" ) { 
250
251                     nodes.push(child);
252                  }
253               }
254            }
255   
256            return nodes;
257         }
258     } 
259     
260     /**
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.
265      *
266      * (code)
267      * t.xml_eq(got, expected, message);
268      * (end)
269      * 
270      * Parameters:
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.
275      *
276      * Valid options:
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.
281      */
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") {
286             try {
287                 got = createNode(got);
288             } catch(err) {
289                 this.fail(msg + ": got argument could not be converted to an XML node: " + err);
290                 return;
291             }
292         }
293         if(typeof expected == "string") {
294             try {
295                 expected = createNode(expected);
296             } catch(err) {
297                 this.fail(msg + ": expected argument could not be converted to an XML node: " + err);
298                 return;
299             }
300         }
301         
302         // test nodes for equivalence
303         try {
304             assertElementNodesEqual(got, expected, options);
305             this.ok(true, msg);
306         } catch(err) {
307             this.fail(msg + ": " + err);
308         }
309     }
310     
311 })();