thunk-test
Advanced tools
Comparing version 1.1.3 to 1.1.5
@@ -208,3 +208,3 @@ module.exports = { | ||
'no-script-url': 'error', | ||
'no-self-compare': 'error', | ||
'no-self-compare': 'off', | ||
'no-sequences': 'off', | ||
@@ -211,0 +211,0 @@ 'no-shadow': 'off', |
165
es.js
@@ -137,3 +137,3 @@ const noop = function () {} | ||
} | ||
let result = `Set { ` | ||
let result = 'Set { ' | ||
const resultValues = [] | ||
@@ -219,8 +219,6 @@ for (const item of value) { | ||
/** | ||
* @name areIteratorsDeepEqual | ||
* | ||
* @synopsis | ||
* areIteratorsDeepEqual(left Iterator, right Iterator) -> boolean | ||
*/ | ||
const sameValueZero = function (left, right) { | ||
return left === right || (left !== left && right !== right); | ||
} | ||
const areIteratorsDeepEqual = function (leftIterator, rightIterator) { | ||
@@ -242,8 +240,2 @@ let leftIteration = leftIterator.next(), | ||
/** | ||
* @name areObjectsDeepEqual | ||
* | ||
* @synopsis | ||
* areObjectsDeepEqual(left Object, right Object) -> boolean | ||
*/ | ||
const areObjectsDeepEqual = function (leftObject, rightObject) { | ||
@@ -263,8 +255,2 @@ const leftKeysLength = objectKeysLength(leftObject), | ||
/** | ||
* @name areArraysDeepEqual | ||
* | ||
* @synopsis | ||
* areArraysDeepEqual(left Array, right Array) -> boolean | ||
*/ | ||
const areArraysDeepEqual = function (leftArray, rightArray) { | ||
@@ -284,48 +270,32 @@ const length = leftArray.length | ||
/** | ||
* @name isDeepEqual | ||
* | ||
* @synopsis | ||
* ```coffeescript [specscript] | ||
* Nested<T> = Array<Array<T>|Object<T>|Iterable<T>|T>|Object<Array<T>|Object<T>|Iterable<T>|T> | ||
* | ||
* var left Nested, | ||
* right Nested | ||
* | ||
* isDeepEqual(left, right) -> boolean | ||
* ``` | ||
* | ||
* @description | ||
* Check two values for deep strict equality. | ||
* | ||
* ```javascript [node] | ||
* console.log( | ||
* isDeepEqual({ a: 1, b: 2, c: [3] }, { a: 1, b: 2, c: [3] }), | ||
* ) // true | ||
* | ||
* console.log( | ||
* isDeepEqual({ a: 1, b: 2, c: [3] }, { a: 1, b: 2, c: [5] }), | ||
* ) // false | ||
* ``` | ||
*/ | ||
const isDeepEqual = function (leftItem, rightItem) { | ||
if (isArray(leftItem) && isArray(rightItem)) { | ||
return areArraysDeepEqual(leftItem, rightItem) | ||
} else if ( | ||
typeof leftItem == 'object' && typeof rightItem == 'object' | ||
&& leftItem != null && rightItem != null | ||
&& leftItem.constructor == rightItem.constructor | ||
&& typeof leftItem[symbolIterator] == 'function' | ||
&& typeof rightItem[symbolIterator] == 'function' | ||
) { | ||
return areIteratorsDeepEqual( | ||
leftItem[symbolIterator](), rightItem[symbolIterator]()) | ||
} else if (leftItem == null || rightItem == null) { | ||
return leftItem === rightItem | ||
} else if ( | ||
leftItem.constructor == Object && rightItem.constructor == Object | ||
) { | ||
return areObjectsDeepEqual(leftItem, rightItem) | ||
const isDeepEqual = function (left, right) { | ||
const isLeftArray = isArray(left), | ||
isRightArray = isArray(right) | ||
if (isLeftArray || isRightArray) { | ||
return isLeftArray && isRightArray | ||
&& areArraysDeepEqual(left, right) | ||
} | ||
return leftItem === rightItem | ||
if (left == null || right == null) { | ||
return sameValueZero(left, right) | ||
} | ||
const isLeftString = typeof left == 'string' || left.constructor == String, | ||
isRightString = typeof right == 'string' || right.constructor == String | ||
if (isLeftString || isRightString) { | ||
return sameValueZero(left, right) | ||
} | ||
const isLeftIterable = typeof left[symbolIterator] == 'function', | ||
isRightIterable = typeof right[symbolIterator] == 'function' | ||
if (isLeftIterable || isRightIterable) { | ||
return isLeftIterable && isRightIterable | ||
&& areIteratorsDeepEqual(left[symbolIterator](), right[symbolIterator]()) | ||
} | ||
const isLeftObject = left.constructor == Object, | ||
isRightObject = right.constructor == Object | ||
if (isLeftObject || isRightObject) { | ||
return isLeftObject && isRightObject | ||
&& areObjectsDeepEqual(left, right) | ||
} | ||
return sameValueZero(left, right) | ||
} | ||
@@ -338,18 +308,11 @@ | ||
* ```coffeescript [specscript] | ||
* assertEqual(expected any, actual any) -> boolean | ||
* assertEqual(expect any, actual any) -> boolean | ||
* ``` | ||
*/ | ||
const assertEqual = function (expected, actual) { | ||
if (typeof expected == 'object' && typeof actual == 'object') { | ||
if (!isDeepEqual(expected, actual)) { | ||
log('expected', expected) | ||
log('actual', actual) | ||
throw AssertionError('not deep equal') | ||
} | ||
} else if (expected !== actual) { | ||
log('expected', expected) | ||
log('actual', actual) | ||
throw AssertionError('not strict equal') | ||
const assertEqual = function (expect, actual) { | ||
if (!isDeepEqual(expect, actual)) { | ||
log('expect', inspect(expect)) | ||
log('actual', inspect(actual)) | ||
throw AssertionError('not equal') | ||
} | ||
return undefined | ||
} | ||
@@ -406,14 +369,14 @@ | ||
* | ||
* errorAssertEqual(expected Error, actual Error) | ||
* errorAssertEqual(expect Error, actual Error) | ||
* ``` | ||
*/ | ||
const errorAssertEqual = function (expected, actual) { | ||
if (actual.name != expected.name) { | ||
const errorAssertEqual = function (expect, actual) { | ||
if (actual.name != expect.name) { | ||
log() | ||
log('-- expect:', expected.name) | ||
log('-- expect:', expect.name) | ||
log('-- actual:', actual.name) | ||
throw AssertionError('error names are different') | ||
} else if (actual.message != expected.message) { | ||
} else if (actual.message != expect.message) { | ||
log() | ||
log('-- expect:', expected.message) | ||
log('-- expect:', expect.message) | ||
log('-- actual:', actual.message) | ||
@@ -506,3 +469,3 @@ throw AssertionError('error messages are different') | ||
if (typeof execution == 'function') { | ||
let cleanup = execution() | ||
const cleanup = execution() | ||
if (isPromise(cleanup)) { | ||
@@ -544,2 +507,3 @@ await cleanup | ||
} | ||
return undefined | ||
} | ||
@@ -581,3 +545,3 @@ | ||
const Test = function (...funcs) { | ||
if (typeof this == null || this.constructor != Test) { | ||
if (this == null || this.constructor != Test) { | ||
return new Test(...funcs) | ||
@@ -594,3 +558,3 @@ } | ||
microPostprocessing = [] | ||
return objectAssign((function thunkTest() { | ||
return objectAssign(function thunkTest() { | ||
if (story != null) { | ||
@@ -620,3 +584,4 @@ log('--', story) | ||
} | ||
}).bind(this), { | ||
return undefined | ||
}, { | ||
@@ -644,10 +609,10 @@ before(callback) { | ||
case(...args) { | ||
const expected = args.pop(), | ||
const expect = args.pop(), | ||
boundArgs = args.map(arg => typeof arg == 'function' ? arg.bind(this) : arg) | ||
if (typeof expected == 'function') { | ||
if (typeof expect == 'function') { | ||
for (const func of funcs) { | ||
operations.push([ | ||
thunkify4(callPropBinary, func, 'apply', this, boundArgs), | ||
curry4(callPropBinary, expected, 'call', this, __), | ||
tapSync(thunkify1(log, ` ✓ ${funcSignature(func, boundArgs)} |> ${funcInspect(expected)}`)), | ||
curry4(callPropBinary, expect, 'call', this, __), | ||
tapSync(thunkify1(log, ` ✓ ${funcSignature(func, boundArgs)} |> ${funcInspect(expect)}`)), | ||
].reduce(funcConcat)) | ||
@@ -659,4 +624,4 @@ } | ||
thunkify4(callPropBinary, func, 'apply', this, boundArgs), | ||
curry2(assertEqual, expected, __), | ||
tapSync(thunkify1(log, ` ✓ ${funcSignature(func, boundArgs)} -> ${inspect(expected)}`)), | ||
curry2(assertEqual, expect, __), | ||
tapSync(thunkify1(log, ` ✓ ${funcSignature(func, boundArgs)} -> ${inspect(expect)}`)), | ||
].reduce(funcConcat)) | ||
@@ -669,5 +634,5 @@ } | ||
throws(...args) { | ||
const expected = args.pop(), | ||
const expect = args.pop(), | ||
boundArgs = args.map(arg => typeof arg == 'function' ? arg.bind(this) : arg) | ||
if (typeof expected == 'function') { | ||
if (typeof expect == 'function') { | ||
for (const func of funcs) { | ||
@@ -682,9 +647,9 @@ operations.push(function tryCatching() { | ||
} catch (error) { | ||
const execution = expected(error, ...boundArgs) | ||
const execution = expect(error, ...boundArgs) | ||
if (isPromise(execution)) { | ||
return execution.then(funcConcat( | ||
tapSync(thunkify1(log, ` ✓ ${funcSignature(func, boundArgs)} throws; ${funcInspect(expected)}`)), | ||
tapSync(thunkify1(log, ` ✓ ${funcSignature(func, boundArgs)} throws; ${funcInspect(expect)}`)), | ||
noop)) | ||
} | ||
log(` ✓ ${funcSignature(func, boundArgs)} throws; ${funcInspect(expected)}`) | ||
log(` ✓ ${funcSignature(func, boundArgs)} throws; ${funcInspect(expect)}`) | ||
return undefined | ||
@@ -702,4 +667,4 @@ } | ||
thunkify4(callPropBinary, func, 'apply', this, boundArgs), | ||
expected), | ||
tapSync(thunkify1(log, ` ✓ ${funcSignature(func, boundArgs)} throws ${errorInspect(expected)}`)), | ||
expect), | ||
tapSync(thunkify1(log, ` ✓ ${funcSignature(func, boundArgs)} throws ${errorInspect(expect)}`)), | ||
)) | ||
@@ -706,0 +671,0 @@ } |
107
index.js
@@ -218,8 +218,6 @@ const noop = function () {} | ||
/** | ||
* @name areIteratorsDeepEqual | ||
* | ||
* @synopsis | ||
* areIteratorsDeepEqual(left Iterator, right Iterator) -> boolean | ||
*/ | ||
const sameValueZero = function (left, right) { | ||
return left === right || (left !== left && right !== right); | ||
} | ||
const areIteratorsDeepEqual = function (leftIterator, rightIterator) { | ||
@@ -241,8 +239,2 @@ let leftIteration = leftIterator.next(), | ||
/** | ||
* @name areObjectsDeepEqual | ||
* | ||
* @synopsis | ||
* areObjectsDeepEqual(left Object, right Object) -> boolean | ||
*/ | ||
const areObjectsDeepEqual = function (leftObject, rightObject) { | ||
@@ -262,8 +254,2 @@ const leftKeysLength = objectKeysLength(leftObject), | ||
/** | ||
* @name areArraysDeepEqual | ||
* | ||
* @synopsis | ||
* areArraysDeepEqual(left Array, right Array) -> boolean | ||
*/ | ||
const areArraysDeepEqual = function (leftArray, rightArray) { | ||
@@ -283,48 +269,32 @@ const length = leftArray.length | ||
/** | ||
* @name isDeepEqual | ||
* | ||
* @synopsis | ||
* ```coffeescript [specscript] | ||
* Nested<T> = Array<Array<T>|Object<T>|Iterable<T>|T>|Object<Array<T>|Object<T>|Iterable<T>|T> | ||
* | ||
* var left Nested, | ||
* right Nested | ||
* | ||
* isDeepEqual(left, right) -> boolean | ||
* ``` | ||
* | ||
* @description | ||
* Check two values for deep strict equality. | ||
* | ||
* ```javascript [node] | ||
* console.log( | ||
* isDeepEqual({ a: 1, b: 2, c: [3] }, { a: 1, b: 2, c: [3] }), | ||
* ) // true | ||
* | ||
* console.log( | ||
* isDeepEqual({ a: 1, b: 2, c: [3] }, { a: 1, b: 2, c: [5] }), | ||
* ) // false | ||
* ``` | ||
*/ | ||
const isDeepEqual = function (leftItem, rightItem) { | ||
if (isArray(leftItem) && isArray(rightItem)) { | ||
return areArraysDeepEqual(leftItem, rightItem) | ||
} else if ( | ||
typeof leftItem == 'object' && typeof rightItem == 'object' | ||
&& leftItem != null && rightItem != null | ||
&& leftItem.constructor == rightItem.constructor | ||
&& typeof leftItem[symbolIterator] == 'function' | ||
&& typeof rightItem[symbolIterator] == 'function' | ||
) { | ||
return areIteratorsDeepEqual( | ||
leftItem[symbolIterator](), rightItem[symbolIterator]()) | ||
} else if (leftItem == null || rightItem == null) { | ||
return leftItem === rightItem | ||
} else if ( | ||
leftItem.constructor == Object && rightItem.constructor == Object | ||
) { | ||
return areObjectsDeepEqual(leftItem, rightItem) | ||
const isDeepEqual = function (left, right) { | ||
const isLeftArray = isArray(left), | ||
isRightArray = isArray(right) | ||
if (isLeftArray || isRightArray) { | ||
return isLeftArray && isRightArray | ||
&& areArraysDeepEqual(left, right) | ||
} | ||
return leftItem === rightItem | ||
if (left == null || right == null) { | ||
return sameValueZero(left, right) | ||
} | ||
const isLeftString = typeof left == 'string' || left.constructor == String, | ||
isRightString = typeof right == 'string' || right.constructor == String | ||
if (isLeftString || isRightString) { | ||
return sameValueZero(left, right) | ||
} | ||
const isLeftIterable = typeof left[symbolIterator] == 'function', | ||
isRightIterable = typeof right[symbolIterator] == 'function' | ||
if (isLeftIterable || isRightIterable) { | ||
return isLeftIterable && isRightIterable | ||
&& areIteratorsDeepEqual(left[symbolIterator](), right[symbolIterator]()) | ||
} | ||
const isLeftObject = left.constructor == Object, | ||
isRightObject = right.constructor == Object | ||
if (isLeftObject || isRightObject) { | ||
return isLeftObject && isRightObject | ||
&& areObjectsDeepEqual(left, right) | ||
} | ||
return sameValueZero(left, right) | ||
} | ||
@@ -341,14 +311,7 @@ | ||
const assertEqual = function (expect, actual) { | ||
if (typeof expect == 'object' && typeof actual == 'object') { | ||
if (!isDeepEqual(expect, actual)) { | ||
log('expect', inspect(expect)) | ||
log('actual', inspect(actual)) | ||
throw AssertionError('not deep equal') | ||
} | ||
} else if (expect !== actual) { | ||
if (!isDeepEqual(expect, actual)) { | ||
log('expect', inspect(expect)) | ||
log('actual', inspect(actual)) | ||
throw AssertionError('not strict equal') | ||
throw AssertionError('not equal') | ||
} | ||
return undefined | ||
} | ||
@@ -355,0 +318,0 @@ |
{ | ||
"name": "thunk-test", | ||
"version": "1.1.3", | ||
"version": "1.1.5", | ||
"description": "Modular testing for JavaScript", | ||
@@ -5,0 +5,0 @@ "author": "Richard Tong", |
@@ -16,5 +16,7 @@ # ThunkTest | ||
Test(identity) | ||
.case(1, 1) | ||
.case(+0, -0) | ||
.case('hey', 'hey') | ||
.case(NaN, result => assert(isNaN(result)))) | ||
.case(NaN, result => { | ||
assert(isNaN(result)) | ||
})) | ||
}) | ||
@@ -28,4 +30,23 @@ // identity | ||
thunk Tests are composed of a string descriptor, a function to test, and test cases denoted by `.case` and `.throws`. Additionally, any test cases may be asynchronous - either by returning a Promise explicitly or using the `async` keyword. | ||
thunk Tests are composed of a string descriptor, a function to test, and test cases denoted by `.case` and `.throws`. Any test cases may be asynchronous - either by returning a Promise explicitly or using the `async` keyword. Both `.case` and `.throws` accept a variadic number of arguments - the same as those provided to the function - with the exception of the last argument: | ||
* not a function - compare the return value directly by [SameValueZero](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) | ||
* an asserter function - pass the return value to theh asserter function and let the asserter handle all the assertions. Note that if this value is a Promise, it is resolved before calling this function | ||
```coffeescript | ||
Test(string, tester function) | ||
.case(...args, expectedResult any) | ||
Test('my test', myFunc) | ||
.case(...args, asserter (result any)=>Promise|()) | ||
Test(string, tester function) | ||
.throws(...args, expectedError Error) | ||
Test('my test', myFunc) | ||
.throws(...args, errorAsserter (error Error, result any)=>Promise|()) | ||
``` | ||
Concisely test many different cases with a declarative, idiomatic API. | ||
```javascript | ||
@@ -32,0 +53,0 @@ Test( |
141
55393
1646