123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- /**
- * Module dependencies
- */
- var util = require('util');
- var _ = require('@sailshq/lodash');
- var rttc = require('rttc');
- var Machine = require('../../');
- var isEquivalent = require('../../node_modules/rttc/spec/helpers/is-equivalent');
- module.exports = function testInputValidation(expectations, cb){
- // Determine type schema of the value.
- // (using inference to pull it from the `example`, if provided)
- var typeSchema;
- if (!_.isUndefined(expectations.typeclass)) {
- if (expectations.typeclass==='dictionary') {
- typeSchema = {};
- }
- else if (expectations.typeclass==='array') {
- typeSchema = [];
- }
- else {
- typeSchema = 'ref';
- }
- }
- else {
- typeSchema = rttc.infer(expectations.example);
- }
- var _inputsInFn;
- var machine = Machine.build({
- inputs: {
- x: (function _determineInputDefinition(){
- var def = {};
- if (_.isUndefined(expectations.required)) {
- // Act like `required` is always present so we can
- // use the existing test suite from `rttc()`.
- def.required = true;
- }
- if (!_.isUndefined(expectations.example)) {
- def.example = expectations.example;
- }
- if (!_.isUndefined(expectations.typeclass)) {
- def.typeclass = expectations.typeclass;
- }
- if (!_.isUndefined(expectations.getExample)) {
- def.getExample = expectations.getExample;
- }
- if (!_.isUndefined(expectations.validate)) {
- def.validate = expectations.validate;
- }
- return def;
- })()
- },
- exits: {
- error: {},
- success: {}
- },
- fn: function (inputs, exits) {
- _inputsInFn = inputs;
- exits();
- }
- })
- .configure({
- x: expectations.actual
- })
- .exec(function (err){
- // validate that error exit was traversed, if expected
- if (err){
- if (expectations.error) return cb();
- return cb(new Error('did not expect machine to call `error`, but it did:\n' + util.inspect(err)));
- }
- else if (expectations.error) {
- // console.log('\nTEST:',expectations);
- // if (_.isObject(expectations.actual)) {
- // console.log('\nactual constructor name:',expectations.actual.constructor.name);
- // }
- // console.log('\nTYPESCHEMA:',typeSchema);
- return cb(new Error('expected machine to call `error` exit due to input validation error, but it did not. ' + ('Instead got '+util.inspect(_inputsInFn.x, false, null))+'.' ));
- }
- if (!_.isObject(_inputsInFn)) {
- return cb(new Error('`inputs` argument in machine fn was corrupted!'));
- }
- // 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;
- // Provide direct access to actual result for clarity in comparisons below.
- var actualResult = _inputsInFn.x;
- // use `isEquivalent` from `rttc`
- if (!isEquivalent(actualResult, compareTo, typeSchema)) {
- return cb(new Error('returned incorrect value: '+util.inspect(actualResult, false, null)));
- }
- // 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!'));
- }
- }
- // If we made it here, everything's good!
- return cb();
- });
- };
|