From 05cc6df770e8ffc25b93c2a482066d7ff7837889 Mon Sep 17 00:00:00 2001 From: Hubert Jacquin Date: Tue, 2 Feb 2016 15:44:42 +0100 Subject: [PATCH 1/4] add done callback. --- index.js | 155 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 74 deletions(-) diff --git a/index.js b/index.js index a4d20e1..2d3b1c8 100644 --- a/index.js +++ b/index.js @@ -5,81 +5,88 @@ var _ = require('lodash'), validator = require('validator'), transform = require('stream-transform'); -module.exports = function(yml, stream, validators) { - - var index = 0, - errorCount = 0, - config = yaml.safeLoad(yml), - settings = _.extend({ columns: true }, config.settings), - parser = parse(settings), - transformer = transform(testRow); - - if (validators && _.isObject(validators)) addValidators(validators); - - stream.pipe(parser).pipe(transformer); - stream.on('end', finish); - - function testRow(row) { - index++; - _.each(row, function(value, field) { - var error = testField(value, field, row); - if (error) console.error(chalk.red(error)); - }); - } - - function testField(value, field, row) { - var fieldIndex = '✗ [row ' + index + ', field ' + field + '] ', - rules = config.fields[field], - output = []; - - rules = _.isString(rules) ? [rules] : rules; - - _.each(rules, function(options, rule) { - if (_.isArray(rules)) { - rule = options; - options = undefined; - } - - if (_.isObject(rule)) { - options = _.values(rule)[0]; - rule = _.keys(rule)[0]; - } - - var args = _.isArray(options) ? - [value].concat(options) : [value, options], - test = validator[rule]; - - if (!test) throw new Error('`' + rule + '` is not a valid rule.'); - - this.row = row; - this.field = field; - this.value = value; - - if (!test.apply(this, args)) { - errorCount = errorCount + 1; - output.push(fieldIndex + '`' + rule + '` failed.'); - } - }); - - return output.join('\n'); - } - - function finish() { - console.log(index + ' rows tested'); - if (errorCount) { - var label = errorCount === 1 ? ' error' : ' errors'; - console.log(chalk.red(errorCount + label + ' found')); - process.exit(1); - } else { - console.log(chalk.green('no errors found')); - process.exit(0); +module.exports = function(yml, stream, validators, doneCallback) { + + var index = 0, + errorCount = 0, + errorList = [], + config = yaml.safeLoad(yml), + settings = _.extend({ columns: true }, config.settings), + parser = parse(settings), + transformer = transform(testRow); + + if (validators && _.isObject(validators)) addValidators(validators); + + stream.pipe(parser).pipe(transformer); + stream.on('end', finish); + + function testRow(row) { + index++; + _.each(row, function(value, field) { + var error = testField(value, field, row); + if (error) console.error(chalk.red(error)); + }); } - } - function addValidators(validators) { - _.each(validators, function(func, key) { - validator.extend(key, func); - }); - } + function testField(value, field, row) { + var fieldIndex = '✗ [row ' + index + ', field ' + field + '] ', + rules = config.fields[field], + output = []; + + rules = _.isString(rules) ? [rules] : rules; + + _.each(rules, function(options, rule) { + if (_.isArray(rules)) { + rule = options; + options = undefined; + } + + if (_.isObject(rule)) { + options = _.values(rule)[0]; + rule = _.keys(rule)[0]; + } + + var args = _.isArray(options) ? + [value].concat(options) : [value, options], + test = validator[rule]; + + if (!test) throw new Error('`' + rule + '` is not a valid rule.'); + + this.row = row; + this.field = field; + this.value = value; + + if (!test.apply(this, args)) { + errorCount = errorCount + 1; + output.push(fieldIndex + '`' + rule + '` failed.'); + if(doneCallback) + errorList.push(output); + } + }); + + return output.join('\n'); + } + + function finish() { + if(doneCallback) doneCallback(errorList); + else finishCli() + } + function finishCli() { + console.log(index + ' rows tested'); + if (errorCount) { + var label = errorCount === 1 ? ' error' : ' errors'; + console.log(chalk.red(errorCount + label + ' found')); + process.exit(1); + } else { + console.log(chalk.green('no errors found')); + process.exit(0); + } + } + + function addValidators(validators) { + _.each(validators, function(func, key) { + validator.extend(key, func); + }); + } }; From 1389dd0df689ec3ee61a8bcc953917181ffb4da4 Mon Sep 17 00:00:00 2001 From: Hubert Jacquin Date: Tue, 16 Feb 2016 11:38:29 +0100 Subject: [PATCH 2/4] add test for require interface --- test/require.test.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 test/require.test.js diff --git a/test/require.test.js b/test/require.test.js new file mode 100644 index 0000000..de1a3f6 --- /dev/null +++ b/test/require.test.js @@ -0,0 +1,37 @@ +var tape = require('tape'); +var fs = require('fs'); + + +tape('require csv-test module', function(t) { + var config = fs.readFileSync('test/fixtures/test.yml', 'utf8'), + file = 'test/fixtures/test.csv', + stream = fs.createReadStream(file, 'utf8'); + + require('..')(config, stream, undefined, function(error){ + t.plan(1); + t.deepEqual(error, [], 'should runs without error'); + }); +}); + +tape('allow fields without rules', function(t) { + var config = fs.readFileSync('test/fixtures/undefinedFields.yml', 'utf8'), + file = 'test/fixtures/test.csv', + stream = fs.createReadStream(file, 'utf8'); + + require('..')(config, stream, undefined, function(error){ + t.plan(1); + t.deepEqual(error, [], 'should runs without error'); + }); +}); + +tape('support custom rules', function(t) { + var config = fs.readFileSync('test/fixtures/customValidators.yml', 'utf8'), + file = 'test/fixtures/customValidators.csv', + validator = require('./fixtures/customValidators.js'), + stream = fs.createReadStream(file, 'utf8'); + + require('..')(config, stream, validator, function(error){ + t.plan(1); + t.deepEqual(error, [], 'should runs without error'); + }); +}); From 816b73a0f1e9c693efb9ec68d5e439064e1cf72d Mon Sep 17 00:00:00 2001 From: Hubert Jacquin Date: Tue, 16 Feb 2016 12:22:40 +0100 Subject: [PATCH 3/4] document usage with require --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 34458dc..d8c8972 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,31 @@ You will see output about your tests that looks like this: 1 error found ``` +## require + +You can use csv-test from a node application using classic require function. + +```js +require('csv-test')(config, stream, validator, callback); +``` + +- **config(str):** Configuration in yaml format. +- **stream(ReadStream):** Data to validate. +- **customValidator:** Custom validator object. +- **callback(function):** Function called when job is finished. + +An example usage might look like this: + +```js +var config = fs.readFileSync('path/to/config.yml', 'utf8'), + stream = fs.createReadStream(path/to/data.csv, 'utf8'); + +require('csv-test')(config, stream, undefined, function(errors) { + // handle list of errors. + console.error(errors) +}); +``` + ## configuration `csv-test` runs by testing your CSV against a configuration file. The configuration file support [yaml](https://en.wikipedia.org/wiki/YAML), which is a human-readable data format. Here is an example configuration file: From e5a661f845e7674cd996ecf8d612dfbca8b1debf Mon Sep 17 00:00:00 2001 From: hubjac1 Date: Tue, 16 Feb 2016 12:27:13 +0100 Subject: [PATCH 4/4] fixe comment typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d8c8972..860211e 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ An example usage might look like this: ```js var config = fs.readFileSync('path/to/config.yml', 'utf8'), - stream = fs.createReadStream(path/to/data.csv, 'utf8'); + stream = fs.createReadStream('path/to/data.csv', 'utf8'); require('csv-test')(config, stream, undefined, function(errors) { // handle list of errors.