Extend expect.js rather than modify the source
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"closure-util": "0.19.0",
|
||||
"expect.js": "~0.3.1",
|
||||
"fs-extra": "~0.8.1",
|
||||
"graceful-fs": "~3.0.2",
|
||||
"jquery": "~2.1.1",
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
|
||||
- spec - includes the OpenLayers test/spec files.
|
||||
|
||||
- expect-0.2.0 - Minimalistic BDD-style assertion framework.
|
||||
https://github.com/LearnBoost/expect.js/
|
||||
|
||||
- test-extensions.js - includes OpenLayers-specific extensions to the
|
||||
testing frameworks.
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,7 @@
|
||||
<div id="mocha"></div>
|
||||
|
||||
<script type="text/javascript" src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<!-- Extended expect.js w/ various methods, see #374 for the differences to 0.2.0 -->
|
||||
<script type="text/javascript" src="expect-0.2.0-ol3/expect.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/expect.js/index.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/sinon/pkg/sinon.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/mocha/mocha.js"></script>
|
||||
<script type="text/javascript" src="test-extensions.js"></script>
|
||||
|
||||
@@ -3,6 +3,21 @@ goog.provide('ol.test.expect.js');
|
||||
|
||||
describe('expect.js', function() {
|
||||
|
||||
describe('arreqlNaN', function() {
|
||||
|
||||
it('considers NaN in array to be equal', function() {
|
||||
expect([1, NaN, 2]).to.arreqlNaN([1, NaN, 2]);
|
||||
expect([1, NaN, 2]).not.to.arreqlNaN([1, 1.5, 2]);
|
||||
});
|
||||
|
||||
it('allows a mix of number and string', function() {
|
||||
expect([1, NaN, 'foo']).to.arreqlNaN([1, NaN, 'foo']);
|
||||
expect([1, NaN, 'foo']).not.to.arreqlNaN([1, NaN, 'bar']);
|
||||
expect([1, NaN]).not.to.arreqlNaN([1, 'foo']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('roughlyEqual', function() {
|
||||
|
||||
it('can tell the difference between 1 and 3', function() {
|
||||
|
||||
@@ -260,31 +260,31 @@ describe('ol.structs.Buffer', function() {
|
||||
it('allows multiple adds and removes', function() {
|
||||
var b = new ol.structs.Buffer(new Array(8), 0);
|
||||
expect(b.add([0, 1])).to.be(0);
|
||||
expect(b.getArray()).to.eql([0, 1, NaN, NaN, NaN, NaN, NaN, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, 1, NaN, NaN, NaN, NaN, NaN, NaN]);
|
||||
expect(b.getCount()).to.be(2);
|
||||
expect(b.add([2, 3, 4, 5])).to.be(2);
|
||||
expect(b.getArray()).to.eql([0, 1, 2, 3, 4, 5, NaN, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, 1, 2, 3, 4, 5, NaN, NaN]);
|
||||
expect(b.getCount()).to.be(6);
|
||||
expect(b.add([6, 7])).to.be(6);
|
||||
expect(b.getArray()).to.eql([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||
expect(b.getCount()).to.be(8);
|
||||
b.remove(2, 2);
|
||||
expect(b.getArray()).to.eql([0, 1, NaN, NaN, 4, 5, 6, 7]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, 1, NaN, NaN, 4, 5, 6, 7]);
|
||||
expect(b.getCount()).to.be(6);
|
||||
expect(b.add([8, 9])).to.be(2);
|
||||
expect(b.getArray()).to.eql([0, 1, 8, 9, 4, 5, 6, 7]);
|
||||
expect(b.getCount()).to.be(8);
|
||||
b.remove(1, 1);
|
||||
expect(b.getArray()).to.eql([0, NaN, 8, 9, 4, 5, 6, 7]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, 4, 5, 6, 7]);
|
||||
expect(b.getCount()).to.be(7);
|
||||
b.remove(4, 4);
|
||||
expect(b.getArray()).to.eql([0, NaN, 8, 9, NaN, NaN, NaN, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, NaN, NaN, NaN, NaN]);
|
||||
expect(b.getCount()).to.be(3);
|
||||
expect(b.add([10, 11, 12])).to.be(4);
|
||||
expect(b.getArray()).to.eql([0, NaN, 8, 9, 10, 11, 12, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, NaN, 8, 9, 10, 11, 12, NaN]);
|
||||
expect(b.getCount()).to.be(6);
|
||||
expect(b.add([13])).to.be(1);
|
||||
expect(b.getArray()).to.eql([0, 13, 8, 9, 10, 11, 12, NaN]);
|
||||
expect(b.getArray()).to.arreqlNaN([0, 13, 8, 9, 10, 11, 12, NaN]);
|
||||
expect(b.getCount()).to.be(7);
|
||||
});
|
||||
|
||||
|
||||
@@ -50,4 +50,261 @@
|
||||
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 =
|
||||
expect.Assertion.prototype.kindaEqual = 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 =
|
||||
expect.Assertion.prototype.totallyWantsToSpeakToYou = 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<ii; ++i) {
|
||||
ga = node1.attributes[i];
|
||||
if (ga.specified === undefined || ga.specified === true) {
|
||||
if (ga.name.split(':').shift() != 'xmlns') {
|
||||
gn = testPrefix ? ga.name : ga.name.split(':').pop();
|
||||
node1Attr[gn] = ga;
|
||||
++node1AttrLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node2.attributes) {
|
||||
for (i=0, ii=node2.attributes.length; i<ii; ++i) {
|
||||
ea = node2.attributes[i];
|
||||
if (ea.specified === undefined || ea.specified === true) {
|
||||
if (ea.name.split(':').shift() != 'xmlns') {
|
||||
en = testPrefix ? ea.name : ea.name.split(':').pop();
|
||||
node2Attr[en] = ea;
|
||||
++node2AttrLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
expect(node1AttrLen).to.equal(node2AttrLen);
|
||||
} catch(e) {
|
||||
errors.push('Number of attributes test failed for: ' + node1.nodeName + ' | ' + e.message);
|
||||
}
|
||||
var gv, ev;
|
||||
for (var name in node1Attr) {
|
||||
if (node2Attr[name] === undefined) {
|
||||
errors.push('Attribute name ' + node1Attr[name].name + ' expected for element ' + node1.nodeName);
|
||||
}
|
||||
// test attribute namespace
|
||||
try {
|
||||
// we do not care about the difference between an empty string and null for namespaceURI
|
||||
// some tests will fail in IE9 otherwise
|
||||
// see also http://msdn.microsoft.com/en-us/library/ff460650(v=vs.85).aspx
|
||||
expect(node1Attr[name].namespaceURI || null).to.be(node2Attr[name].namespaceURI || null);
|
||||
} catch(e) {
|
||||
errors.push('namespaceURI attribute test failed for: ' + node1.nodeName + ' | ' + e.message);
|
||||
}
|
||||
try {
|
||||
expect(node1Attr[name].value).to.equal(node2Attr[name].value);
|
||||
} catch(e) {
|
||||
errors.push('Attribute value test failed for: ' + node1.nodeName + ' | ' + e.message);
|
||||
}
|
||||
}
|
||||
// compare children
|
||||
var node1ChildNodes = getChildNodes(node1, options);
|
||||
var node2ChildNodes = getChildNodes(node2, options);
|
||||
try {
|
||||
expect(node1ChildNodes.length).to.equal(node2ChildNodes.length);
|
||||
} catch(e) {
|
||||
errors.push('Number of childNodes test failed for: ' + node1.nodeName + ' | ' + e.message);
|
||||
}
|
||||
// only compare if they are equal
|
||||
if (node1ChildNodes.length === node2ChildNodes.length) {
|
||||
for (var j=0, jj=node1ChildNodes.length; j<jj; ++j) {
|
||||
assertElementNodesEqual(node1ChildNodes[j], node2ChildNodes[j], options, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the XML document sort of equals another XML document.
|
||||
*/
|
||||
expect.Assertion.prototype.xmleql = function(obj, options) {
|
||||
if (obj && obj.nodeType == 9) {
|
||||
obj = obj.documentElement;
|
||||
}
|
||||
if (this.obj && this.obj.nodeType == 9) {
|
||||
this.obj = this.obj.documentElement;
|
||||
}
|
||||
var errors = [];
|
||||
assertElementNodesEqual(obj, this.obj, options, errors);
|
||||
var result = (errors.length === 0);
|
||||
this.assert(
|
||||
!!result,
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of equal ' + expect.stringify(obj) + '\n' +
|
||||
errors.join('\n');
|
||||
},
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of not equal ' + expect.stringify(obj) + '\n' +
|
||||
errors.join('\n')
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the array sort of equals another array.
|
||||
*/
|
||||
expect.Assertion.prototype.arreql = function (obj) {
|
||||
this.assert(
|
||||
goog.array.equals(this.obj, obj),
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of equal ' + expect.stringify(obj);
|
||||
},
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of not equal ' + expect.stringify(obj);
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the array sort of equals another array (allows NaNs to be equal).
|
||||
*/
|
||||
expect.Assertion.prototype.arreqlNaN = function (obj) {
|
||||
function compare(a, b) {
|
||||
return a === b || (typeof a === 'number' && typeof b === 'number' &&
|
||||
isNaN(a) && isNaN(b));
|
||||
}
|
||||
this.assert(
|
||||
goog.array.equals(this.obj, obj, compare),
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of equal ' + expect.stringify(obj);
|
||||
},
|
||||
function() {
|
||||
return 'expected ' + expect.stringify(this.obj) +
|
||||
' to sort of not equal ' + expect.stringify(obj);
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
})(this);
|
||||
|
||||
Reference in New Issue
Block a user