-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
136 lines (114 loc) · 3.8 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
'use strict'
var deepEqual = require('deep-eql')
var type = require('type-detect')
var DEFAULT_TOLERANCE = 1e-6
/**
* small utility functions
*/
function isNumber (val) {
return type(val) === 'number'
}
function bothNumbers (left, right) {
return isNumber(right) && isNumber(left)
}
function almostEqual (left, right, tol) {
return Math.abs(left - right) <= tol
}
/**
* Makes a comparator function to be passed to deepEqual.
* The returned function will return null if both arguments are not numbers,
* indicating that deepEqual should proceed with other equality checks
*/
function comparator (tolerance) {
return function (left, right) {
if (bothNumbers(left, right)) {
return almostEqual(left, right, tolerance)
}
return null
}
}
/**
* Sets global tolerance and returns a function to be passed to chai.use
* @see http://chaijs.com/guide/plugins/
*/
function chaiAlmost (customTolerance) {
var standardTolerance = customTolerance || DEFAULT_TOLERANCE
return function (chai, utils) {
var Assertion = chai.Assertion
var flag = utils.flag
/**
* Returns a new shallow equality function to override
* .equal, .equals, .eq that tests 'almost' equality
* if both values are numbers and a 'tolerance' flag is set.
* Sends to deep equality check if deep flag is set
*/
function overrideAssertEqual (_super) {
return function assertEqual (val, msg) {
if (msg) flag(this, 'message', msg)
var deep = flag(this, 'deep')
var tolerance = flag(this, 'tolerance')
if (deep) {
return this.eql(val)
} else if (tolerance && bothNumbers(val, this._obj)) {
this.assert(almostEqual(val, this._obj, tolerance),
'expected #{this} to almost equal #{exp}',
'expected #{this} to not almost equal #{exp}',
val,
this._obj,
true
)
} else {
return _super.apply(this, arguments)
}
}
}
/**
* Returns a new deep equality function to override
* .eql, .eqls that tests 'almost' equality if both corresponding
* values are numbers and tolerance flag is set
*/
function overrideAssertEql (_super) {
return function assertEql (val, msg) {
if (msg) flag(this, 'message', msg)
var tolerance = flag(this, 'tolerance')
if (tolerance) {
this.assert(
deepEqual(val, this._obj, { comparator: comparator(tolerance) }),
'expected #{this} to deeply almost equal #{exp}',
'expected #{this} to not deeply almost equal #{exp}',
val,
this._obj,
true
)
} else {
return _super.apply(this, arguments)
}
}
}
/**
* .almost() method. To be used at the end of the chain like:
* expect(4).to.not.be.almost(5, 1.5). Simply adds tolerance flag then calls
* .equal. This will redirect to .eql if deep flag set
*/
function method (val, toleranceOverride) {
var tolerance = toleranceOverride || standardTolerance
flag(this, 'tolerance', tolerance)
return this.equal(val)
}
/**
* .almost chainable property to be used like:
* expect(3.99999999).to.almost.equal(4). Simply adds
* tolerance flag to be read by equality checking methods
*/
function chainingBehavior () {
flag(this, 'tolerance', standardTolerance)
}
Assertion.addChainableMethod('almost', method, chainingBehavior)
Assertion.overwriteMethod('equal', overrideAssertEqual)
Assertion.overwriteMethod('equals', overrideAssertEqual)
Assertion.overwriteMethod('eq', overrideAssertEqual)
Assertion.overwriteMethod('eql', overrideAssertEql)
Assertion.overwriteMethod('eqls', overrideAssertEql)
}
}
module.exports = chaiAlmost