diff --git a/lib/plus.js b/lib/plus.js index deb2e5e..f0d1191 100644 --- a/lib/plus.js +++ b/lib/plus.js @@ -18,40 +18,43 @@ function plus(spec) { gen: () => tcg.null.then(() => tcg.array(gen(spec), {size: _.random(1, 5)})), describe: () => [plus.name, ...describe([spec])], explain: (values, {via}) => { - if (values.length === 0) { - return { - problems: [ - { - path: [], - reason: 'Insufficient input', - val: values, - via, - 'in': [] - } - ] - }; - } else { - const index = _.findIndex(values, value => !isValid(spec, value)); - if (index === -1) { - return null; - } else { - const val = values[index]; - const pred = explainData(spec, val).problems[0].pred; - return { - problems: [ - { - path: [], - pred, - val, - via, - 'in': [index] - } - ] - }; - } + const problems = []; + explainEmptyInput(problems, values, via); + if (_.isEmpty(problems)) { + explainValidInput(problems, spec, values, via); } + return _.isEmpty(problems) ? null : {problems}; } }; } +function explainEmptyInput(problems, values, via) { + if (values.length === 0) { + problems.push({ + path: [], + reason: 'Insufficient input', + val: values, + via, + 'in': [] + }); + } + return problems; +} + +function explainValidInput(problems, spec, values, via) { + const index = _.findIndex(values, value => !isValid(spec, value)); + if (index !== -1) { + const val = values[index]; + const pred = explainData(spec, val).problems[0].pred; + problems.push({ + path: [], + pred, + val, + via, + 'in': [index] + }); + } + return problems; +} + module.exports = plus; diff --git a/test/plus.js b/test/plus.js index f11a7a8..d96f4e2 100644 --- a/test/plus.js +++ b/test/plus.js @@ -13,51 +13,61 @@ describe('Test the plus (+) function', () => { s.def('::odd?', s.and(isInteger, isOdd)); s.def('::odds', s.plus('::odd?')) }); - - it('should return the value', () => { - expect(s.conform('::odds', [1, 3])).to.eql([1, 3]); - }); - - it('should return the invalid string when value sequence is empty', () => { - expect(s.conform('::odds', [])).to.equal(invalidString); - }); - - it('should return the invalid string', () => { - expect(s.conform('::odds', [1, 3, 6])).to.equal(invalidString); - }); - it('should unform a conformed value', () => { - expect(idemPotent('::odds', [1, 3, 5])).to.be.true; + describe('should handle valid input', () => { + it('conform should return the value', () => { + expect(s.conform('::odds', [1, 3])).to.eql([1, 3]); + }); + + it('explainData should return null', () => { + expect(s.explainData('::odds', [1, 3])).to.be.null; + }); }); - it('should implement explain', () => { - expect(s.explainData('::odds', [1, 3, 5])).to.be.null; + describe('should reject empty input', () => { + it('conform should return the invalid string when value sequence is empty', () => { + expect(s.conform('::odds', [])).to.equal(invalidString); + }); - expect(s.explainData('::odds', [])).to.eql({ - problems: [ - { - path: [], - reason: 'Insufficient input', - val: [], - via: ['::odds'], - 'in': [] - } - ] + it('explainData should report a problem', () => { + expect(s.explainData('::odds', [])).to.eql({ + problems: [ + { + path: [], + reason: 'Insufficient input', + val: [], + via: ['::odds'], + 'in': [] + } + ] + }); + }); + }); + + describe('should reject invalid input', () => { + it('should return the invalid string', () => { + expect(s.conform('::odds', [1, 3, 6])).to.equal(invalidString); }); - expect(s.explainData('::odds', [1, 3, 6])).to.eql({ - problems: [ - { - path: [], - pred: 'isOdd', - val: 6, - via: ['::odds'], + it('explainData should report a problem', () => { + expect(s.explainData('::odds', [1, 3, 6])).to.eql({ + problems: [ + { + path: [], + pred: 'isOdd', + val: 6, + via: ['::odds'], 'in': [2] - } - ] + } + ] + }); }); }); + it('should unform a conformed value', () => { + expect(idemPotent('::odds', [1, 3, 5])).to.be.true; + }); + it('should implement a generator', () => { expect(s.exercise(s.plus(isInteger))).to.have.length(10) .to.satisfy(sample => _.every(sample, ([v]) => _.isArray(v) && v.length > 0));