function collOf(predicate, options = {}) { const {kind = _.stubTrue, distinct = false, into} = options; const uniq = value => !distinct || isUnique(value); return { conform: value => { const result = kind(value) && uniq(value) && checkCount(value, options) && _.every(value, v => isValid(predicate, v)); return result ? transform(value, into) : invalidString; }, unform: _.identity, gen: () => tcg.null.then(() => tcg.array(gen(predicate), {size: options.count})), describe: () => [collOf.name, ...describe([predicate]), ...describe(_.flatten(_.toPairs(options)))], explain: function*(values, {via}) { yield* explainCount(values, options, via); yield* explainInvalid(values, predicate, via); } }; }
function fspec(options) { const {args: argsSpec, ret, fn} = options; const funcSpec = fn ? fn : _.stubTrue; return { conform: f => { if (isFunction(f)) { // TODO: Overlap with test/check.js!!! const samples = exercise(argsSpec, 10); const validReturnValue = ([, returnValue]) => isValid(ret, returnValue); const validateFunction = ([args, returnValue]) => funcSpec({ret: returnValue, args: conform(argsSpec, args)}); const results = _.map(samples, ([args]) => [args, f(...args)]); const pass = _.every(results, sample => validReturnValue(sample) && validateFunction(sample)); return pass ? f : invalidString; } else { return invalidString; } } }; }