added files

This commit is contained in:
Ivan Socolsky 2014-12-03 16:41:49 -03:00
parent 6797c3db19
commit 3fc401ea79
2 changed files with 261 additions and 0 deletions

95
js/util/csv.js Normal file
View File

@ -0,0 +1,95 @@
/**
* Small module for exporting data to CSV.
*/
var _ = require('lodash');
var preconditions = require('preconditions').singleton();
var moment = require('../../lib/moment/moment');
var logger = require('../util/log.js');
var config = require('../../config');
var COL_DELIMITER = ',';
var ROW_DELIMITER = '\r\n';
function getValue(obj, property) {
if (_.isFunction(property)) {
try {
return property(obj);
} catch (err) {
if (_.isString(err)) return err;
return undefined;
}
}
if (!_.isObject(obj)) return undefined;
return obj.hasOwnProperty(property) ? obj[property] : undefined;
};
function formatValue(value, type, format) {
if (_.isUndefined(value) || _.isNull(value)) return '';
var r;
switch (type) {
default:
case 'string':
r = value.toString();
r.replace('"', '\\"');
break;
case 'date':
r = moment(value).format(format);
break;
case 'number':
r = value.toString();
break;
}
// escape when commas in values
if (r.indexOf(',') !== -1) {
r = '"' + r + '"';
}
return r;
};
function getHeader(descriptor) {
return _.map(descriptor.columns, function (col) {
return col.label || (_.isString(col.property) ? col.property : '') || '';
});
};
function processDataRow(data, descriptor) {
return _.map(descriptor.columns, function (col) {
var value = getValue(data, col.property);
var formatted = formatValue(value, col.type, col.format);
return formatted;
});
};
/**
* @desc Convert json object to csv based on a descriptor
*
* @param {array} data - the array of json objects to convert to csv
* @param {object} descriptor - an object that parameterizes the conversion
* @param {function} cb - called with the resulting csv
*/
module.exports.toCsv = function(data, descriptor, cb) {
preconditions.shouldBeArray(data);
preconditions.shouldBeObject(descriptor);
preconditions.shouldBeArray(descriptor.columns);
preconditions.shouldBeFunction(cb);
var colDelimiter = descriptor.colDelimiter || COL_DELIMITER;
var rowDelimiter = descriptor.rowDelimiter || ROW_DELIMITER;
var rows = _.map(data, function (dataRow) {
return processDataRow(dataRow, descriptor);
});
var header = getHeader(descriptor);
rows.unshift(header);
var csv = _.reduce(rows, function (memo, row) {
return memo + row.join(colDelimiter) + rowDelimiter;
}, '');
return cb(null, csv);
};

166
test/util.csv.js Normal file
View File

@ -0,0 +1,166 @@
'use strict';
var _ = require('lodash');
var chai = chai || require('chai');
var sinon = sinon || require('sinon');
var should = chai.should();
var csv = require('../js/util/csv')
var moment = require('../lib/moment/moment');
describe('csv utils', function() {
it('should convert simple json', function(done) {
var data = [
{ name: 'Lennon John', age: 40, lastLogin: moment(1417608870000), },
{ name: 'Cobain, Kurt', age: 27, lastLogin: moment('2014-11-01'), },
];
var descriptor = {
columns: [
{ label: 'Name', property: 'name', type: 'string' },
{ label: 'Age', property: 'age', type: 'number' },
{ property: 'lastLogin', type: 'date' },
],
};
csv.toCsv(data, descriptor, function (err, res) {
res.should.equal('Name,Age,lastLogin\r\nLennon John,40,2014-12-03T09:14:30-03:00\r\n"Cobain, Kurt",27,2014-11-01T00:00:00-03:00\r\n');
done();
});
});
it('should handle empty data', function(done) {
var data = [];
var descriptor = {
columns: [
{ label: 'Name', property: 'name', type: 'string' },
{ label: 'Age', property: 'age', type: 'number' },
{ property: 'lastLogin', type: 'date' },
],
};
csv.toCsv(data, descriptor, function (err, res) {
res.should.equal('Name,Age,lastLogin\r\n');
done();
});
});
it('should handle null row in data', function(done) {
var data = [
{ name: 'John', age: 40 },
null,
{ name: 'Kurt', age: 27 },
];
var descriptor = {
columns: [
{ label: 'Name', property: 'name', type: 'string' },
{ label: 'Age', property: 'age', type: 'number' },
],
};
csv.toCsv(data, descriptor, function (err, res) {
res.should.equal('Name,Age\r\nJohn,40\r\n,\r\nKurt,27\r\n');
done();
});
});
it('should format dates', function(done) {
var data = [
{ name: 'John', age: 40, lastLogin: moment(1417608870000), },
{ name: 'Kurt', age: 27, lastLogin: moment('2014-11-01'), },
];
var descriptor = {
columns: [
{ property: 'name', type: 'string' },
{ property: 'age', type: 'number' },
{ property: 'lastLogin', type: 'date', format: 'YYYY MM DD' },
],
};
csv.toCsv(data, descriptor, function (err, res) {
res.should.equal('name,age,lastLogin\r\nJohn,40,2014 12 03\r\nKurt,27,2014 11 01\r\n');
done();
});
});
it('should compute values from function properties', function(done) {
var data = [
{ name: 'John', payments: 400, withdrawals: 300, },
{ name: 'Kurt', payments: 270.5, withdrawals: 200, },
];
var descriptor = {
columns: [
{ property: 'name', type: 'string' },
{ label: 'Balance', property: function (obj) { return obj.payments - obj.withdrawals; }, type: 'number' },
],
};
csv.toCsv(data, descriptor, function (err, res) {
res.should.equal('name,Balance\r\nJohn,100\r\nKurt,70.5\r\n');
done();
});
});
it('should not fail on error from calculated values', function(done) {
var data = [
{ name: 'John', error: 0 },
{ name: 'Kurt', error: 1 },
];
var descriptor = {
columns: [{
property: 'name',
type: 'string'
}, {
label: 'Error',
property: function(obj) {
if (obj.error) {
throw 'dummy error';
} else {
return 'ok';
}
}
}, ],
};
csv.toCsv(data, descriptor, function (err, res) {
res.should.equal('name,Error\r\nJohn,ok\r\nKurt,dummy error\r\n');
done();
});
});
it('should use blank label if label not specified for computed property', function(done) {
var data = [
{ name: 'John', payments: 400, withdrawals: 300, },
{ name: 'Kurt', payments: 270.5, withdrawals: 200, },
];
var descriptor = {
columns: [
{ property: 'name', type: 'string' },
{ property: function (obj) { return obj.payments - obj.withdrawals; }, type: 'number' },
],
};
csv.toCsv(data, descriptor, function (err, res) {
res.should.equal('name,\r\nJohn,100\r\nKurt,70.5\r\n');
done();
});
});
it('should handle non existent properties', function(done) {
var data = [
{ name: 'John', age: 40 },
{ name: 'Kurt', age: 27 },
];
var descriptor = {
columns: [
{ property: 'name', type: 'string' },
{ property: 'age', type: 'number' },
{ property: 'lastLogin', type: 'date', format: 'YYYY MM DD' },
],
};
csv.toCsv(data, descriptor, function (err, res) {
res.should.equal('name,age,lastLogin\r\nJohn,40,\r\nKurt,27,\r\n');
done();
});
});
});