Extend expect.js rather than modify the source
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"closure-util": "0.19.0",
|
"closure-util": "0.19.0",
|
||||||
|
"expect.js": "~0.3.1",
|
||||||
"fs-extra": "~0.8.1",
|
"fs-extra": "~0.8.1",
|
||||||
"graceful-fs": "~3.0.2",
|
"graceful-fs": "~3.0.2",
|
||||||
"jquery": "~2.1.1",
|
"jquery": "~2.1.1",
|
||||||
|
|||||||
@@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
- spec - includes the OpenLayers test/spec files.
|
- 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
|
- test-extensions.js - includes OpenLayers-specific extensions to the
|
||||||
testing frameworks.
|
testing frameworks.
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+1
-2
@@ -10,8 +10,7 @@
|
|||||||
<div id="mocha"></div>
|
<div id="mocha"></div>
|
||||||
|
|
||||||
<script type="text/javascript" src="../node_modules/jquery/dist/jquery.min.js"></script>
|
<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="../node_modules/expect.js/index.js"></script>
|
||||||
<script type="text/javascript" src="expect-0.2.0-ol3/expect.js"></script>
|
|
||||||
<script type="text/javascript" src="../node_modules/sinon/pkg/sinon.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="../node_modules/mocha/mocha.js"></script>
|
||||||
<script type="text/javascript" src="test-extensions.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('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() {
|
describe('roughlyEqual', function() {
|
||||||
|
|
||||||
it('can tell the difference between 1 and 3', 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() {
|
it('allows multiple adds and removes', function() {
|
||||||
var b = new ol.structs.Buffer(new Array(8), 0);
|
var b = new ol.structs.Buffer(new Array(8), 0);
|
||||||
expect(b.add([0, 1])).to.be(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.getCount()).to.be(2);
|
||||||
expect(b.add([2, 3, 4, 5])).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.getCount()).to.be(6);
|
||||||
expect(b.add([6, 7])).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.getArray()).to.eql([0, 1, 2, 3, 4, 5, 6, 7]);
|
||||||
expect(b.getCount()).to.be(8);
|
expect(b.getCount()).to.be(8);
|
||||||
b.remove(2, 2);
|
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.getCount()).to.be(6);
|
||||||
expect(b.add([8, 9])).to.be(2);
|
expect(b.add([8, 9])).to.be(2);
|
||||||
expect(b.getArray()).to.eql([0, 1, 8, 9, 4, 5, 6, 7]);
|
expect(b.getArray()).to.eql([0, 1, 8, 9, 4, 5, 6, 7]);
|
||||||
expect(b.getCount()).to.be(8);
|
expect(b.getCount()).to.be(8);
|
||||||
b.remove(1, 1);
|
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);
|
expect(b.getCount()).to.be(7);
|
||||||
b.remove(4, 4);
|
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.getCount()).to.be(3);
|
||||||
expect(b.add([10, 11, 12])).to.be(4);
|
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.getCount()).to.be(6);
|
||||||
expect(b.add([13])).to.be(1);
|
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);
|
expect(b.getCount()).to.be(7);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -50,4 +50,261 @@
|
|||||||
afterLoad('xml', 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 =
|
||||||
|
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);
|
})(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user