// FIXME remove afterLoadXml as it uses the wrong XML parser on IE9 // helper functions for async testing (function(global) { function afterLoad(type, path, next) { var client = new XMLHttpRequest(); client.open('GET', path, true); client.onload = function() { var data; if (type === 'xml') { data = client.responseXML; } else { data = client.responseText; } if (!data) { throw new Error(path + ' loading failed: ' + client.status); } next(data); }; client.send(); } /** * @param {string} path Relative path to file (e.g. 'spec/ol/foo.json'). * @param {function(Object)} next Function to call with response object on * success. On failure, an error is thrown with the reason. */ global.afterLoadJson = function(path, next) { afterLoad('json', path, next); }; /** * @param {string} path Relative path to file (e.g. 'spec/ol/foo.txt'). * @param {function(string)} next Function to call with response text on * success. On failure, an error is thrown with the reason. */ global.afterLoadText = function(path, next) { afterLoad('text', path, next); }; /** * @param {string} path Relative path to file (e.g. 'spec/ol/foo.xml'). * @param {function(Document)} next Function to call with response xml on * success. On failure, an error is thrown with the reason. */ global.afterLoadXml = function(path, next) { afterLoad('xml', path, next); }; // extensions to expect.js var expect = global.expect; /** * Assert value is within some tolerance of a number. * @param {Number} n Number. * @param {Number} tol Tolerance. */ expect.Assertion.prototype.roughlyEqual = function(n, tol) { this.assert( Math.abs(this.obj - n) <= tol, function() { return 'expected ' + expect.stringify(this.obj) + ' to be within ' + tol + ' of ' + n; }, function() { return 'expected ' + expect.stringify(this.obj) + ' not to be within ' + tol + ' of ' + n; }); return this; }; /** * Assert that a sinon spy was called. */ expect.Assertion.prototype.called = function() { this.assert( this.obj.called, function() { return 'expected ' + expect.stringify(this.obj) + ' to be called'; }, function() { return 'expected ' + expect.stringify(this.obj) + ' not to be called'; }); return this; }; function getChildNodes(node, options) { // check whitespace if (options && options.includeWhiteSpace) { return node.childNodes; } else { var nodes = []; for (var i = 0, ii=node.childNodes.length; i < ii; i++ ) { var child = node.childNodes[i]; if (child.nodeType == 1) { // element node, add it nodes.push(child); } else if (child.nodeType == 3) { // text node, add if non empty if (child.nodeValue && child.nodeValue.replace(/^\s*(.*?)\s*$/, '$1') !== '') { nodes.push(child); } } } return nodes; } } function assertElementNodesEqual(node1, node2, options, errors) { var testPrefix = (options && options.prefix === true); try { expect(node1.nodeType).to.equal(node2.nodeType); } catch(e) { errors.push('nodeType test failed for: ' + node1.nodeName + ' | ' + node2.nodeName + ' | ' + e.message); } if (testPrefix) { try { expect(node1.nodeName).to.equal(node2.nodeName); } catch(e) { errors.push('nodeName test failed for: ' + node1.nodeName + ' | ' + node2.nodeName + ' | ' + e.message); } } else { try { expect(node1.nodeName.split(':').pop()).to.equal( node2.nodeName.split(':').pop()); } catch(e) { errors.push('nodeName test failed for: ' + node1.nodeName + ' | ' + node2.nodeName + ' | ' + e.message); } } // for text nodes compare value if (node1.nodeType === 3) { try { // TODO should we make this optional? expect(node1.nodeValue.replace(/\s/g, '')).to.equal( node2.nodeValue.replace(/\s/g, '')); } catch(e) { errors.push('nodeValue test failed | ' + e.message); } } // for element type nodes compare namespace, attributes, and children else if (node1.nodeType === 1) { // test namespace alias and uri if (node1.prefix || node2.prefix) { if (testPrefix) { try { expect(node1.prefix).to.equal(node2.prefix); } catch(e) { errors.push('Prefix test failed for: ' + node1.nodeName + ' | ' + e.message); } } } if (node1.namespaceURI || node2.namespaceURI) { try { expect(node1.namespaceURI).to.equal(node2.namespaceURI); } catch(e) { errors.push('namespaceURI test failed for: ' + node1.nodeName + ' | ' + e.message); } } // compare attributes - disregard xmlns given namespace handling above var node1AttrLen = 0; var node1Attr = {}; var node2AttrLen = 0; var node2Attr = {}; var ga, ea, gn, en; var i, ii; if (node1.attributes) { for (i=0, ii=node1.attributes.length; i