rttc
Version:
Runtime type-checking for JavaScript.
105 lines (84 loc) • 4.04 kB
JavaScript
/**
* Module dependencies
*/
var util = require('util');
var _ = require('@sailshq/lodash');
var infer = require('../../lib/infer');
var getDisplayType = require('../../lib/get-display-type');
var isEqual = require('../../lib/is-equal');
var getAbbreviatedDisplayVal = require('../../lib/helpers/get-abbreviated-display-val');
module.exports = function toRunTestWith(transformationFn) {
return function _runTest(expectations, cb){
// Determine type schema of the value.
// (using inference to pull it from the `example`, if provided)
var typeSchema;
if (!_.isUndefined(expectations.type)) {
typeSchema = expectations.type;
}
else {
typeSchema = infer(expectations.example);
}
// Create backup copies of our type schema and example
// (we validate whether they were inadvertently changed below)
var originalExampleBackup = _.cloneDeep(expectations.example);
var originalTypeSchemaBackup = _.cloneDeep(typeSchema);
// Now validate and/or coerce the actual value against the type schema.
var actualResult;
var gotError;
try {
actualResult = transformationFn(typeSchema, expectations.actual);
}
catch (e) {
gotError = e;
}
// Finally, make sure the right thing happened and that we
// got the appropriate result.
//
//
// Ensure that if we got an error, we were expecting it.
if (gotError){
if (expectations.error) {return cb();}
return cb(new Error('did not expect error, but got one:\n' + util.inspect(gotError) + '\n\nHere is the stack from the error:\n'+gotError.stack+'\n' ));
}
// Handle case where we were expecting an error, but we didn't get one.
if (expectations.error) {
return cb(new Error('expected a error, but did not get one. Instead, returned '+util.inspect(actualResult, false, null)+'.'));
}
// If an expected `result` is provided, compare the actual result against that.
// Otherwise compare it against the original value (`actual`)
var compareTo = expectations.hasOwnProperty('result') ? expectations.result : expectations.actual;
if (!isEqual(actualResult, compareTo, typeSchema)) {
return cb(new Error('returned incorrect value: '+getAbbreviatedDisplayVal(actualResult)+' (a '+getDisplayType(actualResult)+')'));
}
// Test using strict equality (===) if explicitly requested
if (expectations.strictEq) {
if (actualResult !== compareTo) {
return cb(new Error('returned value is equivalent (but not ===)'));
}
}
// Test AGAINST strict equality using `isNew` if requested
// (i.e. guarantees this is a new value and is !== what was passed in)
if (expectations.isNew) {
// Check both the expected result and the actual value, just to be safe.
// (should never even be possible for it to be a direct reference to the expected result)
if (actualResult === compareTo || actualResult === expectations.actual) {
return cb(new Error('returned value === value that was passed in -- but should have been a new value!'));
}
}
// Test that the `example` originally passed in, as well as the
// inferred `typeSchema`, have not been altered.
//
// (The `typeSchema` should NEVER change as a result of running this test.
// And neither should `expectations.example`, if it was provided.)
if (!isEqual(typeSchema, originalTypeSchemaBackup)) {
return cb(new Error('inferred type schema was modified as a result of running test!! it became: '+util.inspect(typeSchema, {depth: null})+' (a '+getDisplayType(typeSchema)+')'));
}
if (!_.isUndefined(originalExampleBackup)) {
if (!isEqual(expectations.example, originalExampleBackup)) {
return cb(new Error('`example` was modified as a result of running test!! it became: '+util.inspect(expectations.example, {depth: null})+' (a '+getDisplayType(expectations.example)+')'));
}
}
// If we made it here, everything's good!
return cb();
};
};