Merge pull request #971 from CartoDB/cartovl-130

Send dates as unix epoch instead strings in .mvt files
This commit is contained in:
Javier Goizueta
2018-06-13 13:07:35 +02:00
committed by GitHub
11 changed files with 515 additions and 38 deletions
+265
View File
@@ -0,0 +1,265 @@
/* eslint-env mocha */
const assert = require('assert');
const TestClient = require('../support/test-client');
const mapConfigFactory = require('../fixtures/test_mapconfigFactory');
describe('date-wrapping', () => {
let testClient;
describe('when a map instantiation has one single layer', () => {
describe('and the layer has the "dates_as_numbers" option enabled', () => {
beforeEach(() => {
const mapConfig = mapConfigFactory.getVectorMapConfig({ layerOptions: [{ dates_as_numbers: true }]});
testClient = new TestClient(mapConfig);
});
afterEach(done => testClient.drain(done));
it('should return date columns casted as numbers', done => {
testClient.getTile(0, 0, 0, { format: 'mvt' }, (err, res, mvt) => {
const expected = [
{
type: 'Feature',
id: 1,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 0, date: 1527810000 }
},
{
type: 'Feature',
id: 2,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 1, date: 1527900000 }
}
];
const actual = JSON.parse(mvt.toGeoJSONSync(0)).features;
assert.deepEqual(actual, expected);
done();
});
});
it('should return metadata with casted columns', done => {
testClient.getLayergroup(function(err, layergroup) {
assert.ifError(err);
assert.deepEqual(layergroup.metadata.layers[0].meta.dates_as_numbers, ['date']);
done();
});
});
});
describe('and the layer has the "dates_as_numbers" option disabled', () => {
beforeEach(() => {
const mapConfig = mapConfigFactory.getVectorMapConfig({ layerOptions: [{ dates_as_numbers: false }]});
testClient = new TestClient(mapConfig);
});
afterEach(done => testClient.drain(done));
it('should return date columns as dates', done => {
testClient.getTile(0, 0, 0, { format: 'mvt' }, (err, res, mvt) => {
const expected = [
{
type: 'Feature',
id: 1,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 0 }
},
{
type: 'Feature',
id: 2,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 1 }
}
];
const actual = JSON.parse(mvt.toGeoJSONSync(0)).features;
assert.deepEqual(actual, expected);
done();
});
});
});
});
describe('when a map instantiation has multiple layers', () => {
afterEach(done => testClient.drain(done));
describe('and both layers have the "dates_as_numbers" option enabled', () => {
beforeEach(() => {
const mapConfig = mapConfigFactory.getVectorMapConfig({
numberOfLayers: 2,
layerOptions: [
{ dates_as_numbers: true },
{ dates_as_numbers: true }
]
});
testClient = new TestClient(mapConfig);
});
it('should return dates as numbers for every layer', done => {
testClient.getLayergroup(function(err, layergroup) {
assert.ifError(err);
assert.deepEqual(layergroup.metadata.layers[0].meta.dates_as_numbers, ['date']);
assert.deepEqual(layergroup.metadata.layers[1].meta.dates_as_numbers, ['date']);
});
testClient.getTile(0, 0, 0, { format: 'mvt' }, (err, res, mvt) => {
const expected0 = [
{
type: 'Feature',
id: 1,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 0, date: 1527810000 }
},
{
type: 'Feature',
id: 2,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 1, date: 1527900000 }
}
];
const expected1 = [
{
type: 'Feature',
id: 1,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 0, date: 1527810000 }
},
{
type: 'Feature',
id: 2,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 1, date: 1527900000 }
}
];
const actual0 = JSON.parse(mvt.toGeoJSONSync(0)).features;
const actual1 = JSON.parse(mvt.toGeoJSONSync(1)).features;
assert.deepEqual(actual0, expected0);
assert.deepEqual(actual1, expected1);
done();
});
});
});
describe('and only one layers has the "dates_as_numbers" option enabled', () => {
beforeEach(() => {
const mapConfig = mapConfigFactory.getVectorMapConfig({
numberOfLayers: 2,
layerOptions: [
{ dates_as_numbers: false },
{ dates_as_numbers: true }
]
});
testClient = new TestClient(mapConfig);
});
it('should return dates as numbers only for the layer with the "dates_as_numbers" flag enabled', done => {
testClient.getLayergroup(function(err, layergroup) {
assert.ifError(err);
assert.deepEqual(layergroup.metadata.layers[0].meta.dates_as_numbers || [], []);
assert.deepEqual(layergroup.metadata.layers[1].meta.dates_as_numbers, ['date']);
});
testClient.getTile(0, 0, 0, { format: 'mvt' }, (err, res, mvt) => {
const expected0 = [
{
type: 'Feature',
id: 1,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 0 }
},
{
type: 'Feature',
id: 2,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 1 }
}
];
const expected1 = [
{
type: 'Feature',
id: 1,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 0, date: 1527810000 }
},
{
type: 'Feature',
id: 2,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 1, date: 1527900000 }
}
];
const actual0 = JSON.parse(mvt.toGeoJSONSync(0)).features;
const actual1 = JSON.parse(mvt.toGeoJSONSync(1)).features;
assert.deepEqual(actual0, expected0);
assert.deepEqual(actual1, expected1);
done();
});
});
});
describe('and none of the layers has the "dates_as_numbers" option enabled', () => {
beforeEach(() => {
const mapConfig = mapConfigFactory.getVectorMapConfig({
numberOfLayers: 2,
layerOptions: [
{ dates_as_numbers: false },
{ dates_as_numbers: false }
]
});
testClient = new TestClient(mapConfig);
});
it('should return dates as dates for both layers', done => {
testClient.getLayergroup(function(err, layergroup) {
assert.ifError(err);
assert.deepEqual(layergroup.metadata.layers[0].meta.dates_as_numbers || [], []);
assert.deepEqual(layergroup.metadata.layers[1].meta.dates_as_numbers || [], []);
});
testClient.getTile(0, 0, 0, { format: 'mvt' }, (err, res, mvt) => {
const expected0 = [
{
type: 'Feature',
id: 1,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 0 }
},
{
type: 'Feature',
id: 2,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 1 }
}
];
const expected1 = [
{
type: 'Feature',
id: 1,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 0 }
},
{
type: 'Feature',
id: 2,
geometry: { type: 'Point', coordinates: [0, 0] },
properties: { _cdb_feature_count: 1, cartodb_id: 1 }
}
];
const actual0 = JSON.parse(mvt.toGeoJSONSync(0)).features;
const actual1 = JSON.parse(mvt.toGeoJSONSync(1)).features;
assert.deepEqual(actual0, expected0);
assert.deepEqual(actual1, expected1);
done();
});
});
});
});
});
+62
View File
@@ -0,0 +1,62 @@
function getVectorMapConfig(opts) {
return {
buffersize: {
mvt: 1
},
layers: _generateLayers(opts),
};
}
function _generateLayers(opts) {
const numberOfLayers = opts.numberOfLayers || 1;
const layers = [];
for (let index = 0; index < numberOfLayers; index++) {
const layerOptions = (opts.layerOptions || {})[index] || {};
layers.push(_generateLayerConfig(layerOptions));
}
return layers;
}
function _generateLayerConfig(opts) {
return {
type: 'mapnik',
options: {
sql: `
SELECT
(DATE '2018-06-01' + x) as date,
x as cartodb_id,
st_makepoint(x * 10, x * 10) as the_geom,
st_makepoint(x * 10, x * 10) as the_geom_webmercator
FROM
generate_series(0, 1) x`,
aggregation: {
columns: {},
dimensions: {
date: 'date'
},
placement: 'centroid',
resolution: 1,
threshold: 1
},
dates_as_numbers: opts.dates_as_numbers,
metadata: {
geometryType: true,
columnStats: {
topCategories: 32768,
includeNulls: true
},
sample: {
num_rows: 1000,
include_columns: [
'date'
]
}
}
}
};
}
module.exports = { getVectorMapConfig };