diff --git a/.gitignore b/.gitignore index b39f2801..83bce537 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,5 @@ tools/munin/windshaft.conf logs/ pids/ redis.pid -test.log -npm-debug.log +*.log coverage/ diff --git a/lib/cartodb/backends/template_maps.js b/lib/cartodb/backends/template_maps.js index bb728181..75a482fe 100644 --- a/lib/cartodb/backends/template_maps.js +++ b/lib/cartodb/backends/template_maps.js @@ -296,7 +296,7 @@ TemplateMaps.prototype.delTemplate = function(owner, tpl_id, callback) { // @param callback function(err) // TemplateMaps.prototype.updTemplate = function(owner, tpl_id, template, callback) { - + var self = this; template = templateDefaults(template); @@ -430,13 +430,17 @@ var _reNumber = /^([-+]?[\d\.]?\d+([eE][+-]?\d+)?)$/, _reCSSColorVal = /^#[0-9a-fA-F]{3,6}$/; function _replaceVars (str, params) { - //return _.template(str, params); // lazy way, possibly dangerous - // Construct regular expressions for each param + // Construct regular expressions for each param Object.keys(params).forEach(function(k) { str = str.replace(new RegExp("<%=\\s*" + k + "\\s*%>", "g"), params[k]); }); return str; } + +function isObject(val) { + return ( _.isObject(val) && !_.isArray(val) && !_.isFunction(val)); +} + TemplateMaps.prototype.instance = function(template, params) { var all_params = {}; var phold = template.placeholders || {}; @@ -474,6 +478,13 @@ TemplateMaps.prototype.instance = function(template, params) { // NOTE: we're deep-cloning the layergroup here var layergroup = JSON.parse(JSON.stringify(template.layergroup)); + + if (layergroup.buffersize && isObject(layergroup.buffersize)) { + Object.keys(layergroup.buffersize).forEach(function(k) { + layergroup.buffersize[k] = parseInt(_replaceVars(layergroup.buffersize[k], all_params), 10); + }); + } + for (var i=0; i 0) { var nestedNamedMapsError = new Error('Nested named layers are not allowed'); - // nestedNamedMapsError.http_status = 400; return done(nestedNamedMapsError); } diff --git a/lib/cartodb/models/mapconfig/provider/named-map-provider.js b/lib/cartodb/models/mapconfig/provider/named-map-provider.js index 2439a650..594ec247 100644 --- a/lib/cartodb/models/mapconfig/provider/named-map-provider.js +++ b/lib/cartodb/models/mapconfig/provider/named-map-provider.js @@ -90,6 +90,7 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) { }, function instantiateTemplate(err, templateParams) { assert.ifError(err); + context.templateParams = templateParams; return self.templateMaps.instance(self.template, templateParams); }, function prepareAdapterMapConfig(err, requestMapConfig) { diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index b695a367..273f34c1 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -35,6 +35,7 @@ var timeoutErrorTile = require('fs').readFileSync(timeoutErrorTilePath, {encodin var SqlWrapMapConfigAdapter = require('./models/mapconfig/adapter/sql-wrap-mapconfig-adapter'); var MapConfigNamedLayersAdapter = require('./models/mapconfig/adapter/mapconfig-named-layers-adapter'); +var MapConfigBufferSizeAdapter = require('./models/mapconfig/adapter/mapconfig-buffer-size-adapter'); var AnalysisMapConfigAdapter = require('./models/mapconfig/adapter/analysis-mapconfig-adapter'); var MapConfigOverviewsAdapter = require('./models/mapconfig/adapter/mapconfig-overviews-adapter'); var TurboCartoAdapter = require('./models/mapconfig/adapter/turbo-carto-adapter'); @@ -155,6 +156,7 @@ module.exports = function(serverOptions) { var mapConfigAdapter = new MapConfigAdapter( new MapConfigNamedLayersAdapter(templateMaps, pgConnection), + new MapConfigBufferSizeAdapter(), new SqlWrapMapConfigAdapter(), new DataviewsWidgetsAdapter(), new AnalysisMapConfigAdapter(analysisBackend), diff --git a/package.json b/package.json index 00e2f520..d33bb526 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "step-profiler": "~0.3.0", "turbo-carto": "0.19.0", "underscore": "~1.6.0", - "windshaft": "3.1.2", + "windshaft": "3.2.0", "yargs": "~5.0.0" }, "devDependencies": { diff --git a/test/acceptance/buffer-size-format.js b/test/acceptance/buffer-size-format.js new file mode 100644 index 00000000..d5157585 --- /dev/null +++ b/test/acceptance/buffer-size-format.js @@ -0,0 +1,424 @@ +require('../support/test_helper'); + +var fs = require('fs'); +var assert = require('../support/assert'); +var TestClient = require('../support/test-client'); +var mapnik = require('windshaft').mapnik; +var IMAGE_TOLERANCE_PER_MIL = 5; + +var CARTOCSS_LABELS = [ + '#layer {', + ' polygon-fill: #374C70;', + ' polygon-opacity: 0.9;', + ' line-width: 1;', + ' line-color: #FFF;', + ' line-opacity: 0.5;', + '}', + '#layer::labels {', + ' text-name: [name];', + ' text-face-name: \'DejaVu Sans Book\';', + ' text-size: 20;', + ' text-fill: #FFFFFF;', + ' text-label-position-tolerance: 0;', + ' text-halo-radius: 1;', + ' text-halo-fill: #6F808D;', + ' text-dy: -10;', + ' text-allow-overlap: true;', + ' text-placement: point;', + ' text-placement-type: dummy;', + '}' +].join('\n'); + +function createMapConfig (bufferSize, cartocss) { + cartocss = cartocss || CARTOCSS_LABELS; + + return { + version: '1.6.0', + buffersize: bufferSize, + layers: [{ + type: "cartodb", + options: { + sql: [ + 'select', + ' *', + 'from', + ' populated_places_simple_reduced', + ].join('\n'), + cartocss: cartocss, + cartocss_version: '2.3.0', + interactivity: 'cartodb_id' + } + }] + }; +} + +describe('buffer size per format', function () { + var testCases = [ + { + desc: 'should get png tile using buffer-size 0', + coords: { z: 7, x: 64, y: 48 }, + format: 'png', + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-0.png', + mapConfig: createMapConfig({ png: 0, 'grid.json': 0 }), + assert: function (tile, callback) { + assert.imageIsSimilarToFile(tile, this.fixturePath, IMAGE_TOLERANCE_PER_MIL, callback); + } + }, + { + desc: 'should get png tile using buffer-size 128', + coords: { z: 7, x: 64, y: 48 }, + format: 'png', + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.png', + mapConfig: createMapConfig({ png: 128, 'grid.json': 128 }), + assert: function (tile, callback) { + assert.imageIsSimilarToFile(tile, this.fixturePath, IMAGE_TOLERANCE_PER_MIL, callback); + } + }, + { + desc: 'should get mvt tile using buffer-size 0', + coords: { z: 7, x: 64, y: 48 }, + format: 'mvt', + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-0.mvt', + mapConfig: createMapConfig({ mvt: 0 }), + assert: function (tile, callback) { + var tileJSON = tile.toJSON(); + var features = tileJSON[0].features; + assert.equal(features.length, 1); + callback(); + } + }, + { + desc: 'should get mvt tile using buffer-size 128', + coords: { z: 7, x: 64, y: 48 }, + format: 'mvt', + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.mvt', + mapConfig: createMapConfig({ mvt: 128 }), + assert: function (tile, callback) { + var tileJSON = tile.toJSON(); + var features = tileJSON[0].features; + assert.equal(features.length, 9); + callback(); + } + }, + { + desc: 'should get grid.json tile using buffer-size 0 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'grid.json', + layers: [0], + fixturePath: './test/fixtures/buffer-size/tile-grid.json.7.64.48-buffer-size-0.grid.json', + mapConfig: createMapConfig({ 'grid.json': 0 }), + assert: function (tile, callback) { + assert.utfgridEqualsFile(tile, this.fixturePath, 2,callback); + } + }, + { + desc: 'should get grid.json tile using buffer-size 128 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'grid.json', + layers: [0], + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.grid.json', + mapConfig: createMapConfig({ 'grid.json': 128 }), + assert: function (tile, callback) { + assert.utfgridEqualsFile(tile, this.fixturePath, 2, callback); + } + } + ]; + + testCases.forEach(function (test) { + it(test.desc, function (done) { + var testClient = new TestClient(test.mapConfig, 1234); + var coords = test.coords; + var options = { + format: test.format, + layers: test.layers + }; + testClient.getTile(coords.z, coords.x, coords.y, options, function (err, res, tile) { + assert.ifError(err); + // To generate images use: + // tile.save(test.fixturePath); + test.assert(tile, function (err) { + assert.ifError(err); + testClient.drain(done); + }); + }); + }); + }); +}); + +function createBufferSizeTemplate (name, buffersize, placeholders, cartocss) { + cartocss = cartocss || CARTOCSS_LABELS; + + return { + "version": "0.0.1", + "name": name, + "placeholders": placeholders || { + "buffersize": { + "type": "number", + "default": 0 + } + }, + "layergroup": createMapConfig(buffersize) + }; +} + +describe('buffer size per format for named maps', function () { + var testCases = [ + { + desc: 'should get png tile using buffer-size 0 (default value in template)', + coords: { z: 7, x: 64, y: 48 }, + format: 'png', + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-0.png', + template: createBufferSizeTemplate('named-default-buffer-size', {png: '<%= buffersize %>'}), + assert: function (tile, callback) { + assert.imageIsSimilarToFile(tile, this.fixturePath, IMAGE_TOLERANCE_PER_MIL, callback); + } + }, + { + desc: 'should get png tile using buffer-size 128 (placehoder value)', + coords: { z: 7, x: 64, y: 48 }, + format: 'png', + placeholders: { buffersize: 128 }, + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.png', + template: createBufferSizeTemplate('named-custom-buffer-size', { png: '<%= buffersize %>'}), + assert: function (tile, callback) { + assert.imageIsSimilarToFile(tile, this.fixturePath, IMAGE_TOLERANCE_PER_MIL, callback); + } + }, + { + desc: 'should get png tile using buffer-size 0 (default value in template by format)', + coords: { z: 7, x: 64, y: 48 }, + format: 'png', + placeholders: { buffersize_png: 0 }, + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-0.png', + template: createBufferSizeTemplate('named-default-buffer-size-by-format', { + png: '<%= buffersize_png %>' + }, { + "buffersize_png": { + "type": "number", + "default": "0" + } + }), + assert: function (tile, callback) { + assert.imageIsSimilarToFile(tile, this.fixturePath, IMAGE_TOLERANCE_PER_MIL, callback); + } + }, + { + desc: 'should get png tile using buffer-size 128 (placehoder value in template by format)', + coords: { z: 7, x: 64, y: 48 }, + format: 'png', + placeholders: { buffersize_png: 128 }, + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.png', + template: createBufferSizeTemplate('named-custom-buffer-size-by-format', { + png: '<%= buffersize_png %>' + }, { + "buffersize_png": { + "type": "number", + "default": "0" + } + }), + assert: function (tile, callback) { + assert.imageIsSimilarToFile(tile, this.fixturePath, IMAGE_TOLERANCE_PER_MIL, callback); + } + }, + { + desc: 'should get grid.json tile using buffer-size 0 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'grid.json', + layers: [0], + placeholders: { buffersize_gridjson: 0 }, + fixturePath: './test/fixtures/buffer-size/tile-grid.json.7.64.48-buffer-size-0.grid.json', + template: createBufferSizeTemplate('named-default-buffer-size-by-format-gridjson', { + 'grid.json': '<%= buffersize_gridjson %>' + }, { + "buffersize_gridjson": { + "type": "number", + "default": "0" + } + }), + assert: function (tile, callback) { + assert.utfgridEqualsFile(tile, this.fixturePath, 2,callback); + } + }, + { + desc: 'should get grid.json tile using buffer-size 128 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'grid.json', + layers: [0], + placeholders: { buffersize_gridjson: 128 }, + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.grid.json', + template: createBufferSizeTemplate('named-custom-buffer-size-by-format-gridjson', { + 'grid.json': '<%= buffersize_gridjson %>' + }, { + "buffersize_gridjson": { + "type": "number", + "default": "0" + } + }), + assert: function (tile, callback) { + assert.utfgridEqualsFile(tile, this.fixturePath, 2, callback); + } + } + ]; + + testCases.forEach(function (test) { + it(test.desc, function (done) { + var testClient = new TestClient(test.template, 1234); + var coords = test.coords; + var options = { + format: test.format, + placeholders: test.placeholders, + layers: test.layers + }; + testClient.getTile(coords.z, coords.x, coords.y, options, function (err, res, tile) { + assert.ifError(err); + // To generate images use: + //tile.save('./test/fixtures/buffer-size/tile-7.64.48-buffer-size-0-test.png'); + test.assert(tile, function (err) { + assert.ifError(err); + testClient.drain(done); + }); + }); + }); + }); +}); + + +describe('buffer size per format for named maps w/o placeholders', function () { + var testCases = [ + { + desc: 'should get png tile using buffer-size 0 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'png', + placeholders: { + buffersize: { + png: 0 + } + }, + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-0.png', + template: createBufferSizeTemplate('named-no-buffer-size-png-0', {}, {}), + assert: function (tile, callback) { + assert.imageIsSimilarToFile(tile, this.fixturePath, IMAGE_TOLERANCE_PER_MIL, callback); + } + }, + { + desc: 'should get png tile using buffer-size 128 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'png', + placeholders: { + buffersize: { + png: 128 + } + }, + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.png', + template: createBufferSizeTemplate('named-no-buffer-size-png-128', {}, {}), + assert: function (tile, callback) { + assert.imageIsSimilarToFile(tile, this.fixturePath, IMAGE_TOLERANCE_PER_MIL, callback); + } + }, + { + desc: 'should get mvt tile using buffer-size 0 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'mvt', + placeholders: { + buffersize: { + mvt: 0 + } + }, + fixturePath: './test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-0.mvt', + template: createBufferSizeTemplate('named-no-buffer-size-mvt', {}, {}), + assert: function (tile, callback) { + var tileJSON = tile.toJSON(); + var features = tileJSON[0].features; + + var dataFixture = fs.readFileSync(this.fixturePath); + var vtile = new mapnik.VectorTile(this.coords.z, this.coords.x, this.coords.y); + vtile.setDataSync(dataFixture); + var vtileJSON = vtile.toJSON(); + var vtileFeatures = vtileJSON[0].features; + + assert.equal(features.length, vtileFeatures.length); + callback(); + } + }, + { + desc: 'should get mvt tile using buffer-size 128 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'mvt', + placeholders: { + buffersize: { + mvt: 128 + } + }, + fixturePath: './test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-128.mvt', + template: createBufferSizeTemplate('named-no-buffer-size-mvt-128', {}, {}), + assert: function (tile, callback) { + var tileJSON = tile.toJSON(); + var features = tileJSON[0].features; + + var dataFixture = fs.readFileSync(this.fixturePath); + var vtile = new mapnik.VectorTile(this.coords.z, this.coords.x, this.coords.y); + vtile.setDataSync(dataFixture); + var vtileJSON = vtile.toJSON(); + var vtileFeatures = vtileJSON[0].features; + + assert.equal(features.length, vtileFeatures.length); + callback(); + } + }, + { + desc: 'should get grid.json tile using buffer-size 0 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'grid.json', + layers: [0], + placeholders: { + buffersize: { + 'grid.json': 0 + } + }, + fixturePath: './test/fixtures/buffer-size/tile-grid.json.7.64.48-buffer-size-0.grid.json', + template: createBufferSizeTemplate('named-no-buffer-size-grid-json-0', {}, {}), + assert: function (tile, callback) { + assert.utfgridEqualsFile(tile, this.fixturePath, 2,callback); + } + }, + { + desc: 'should get grid.json tile using buffer-size 128 overriden by template params', + coords: { z: 7, x: 64, y: 48 }, + format: 'grid.json', + layers: [0], + placeholders: { + buffersize: { + 'grid.json': 128 + } + }, + fixturePath: './test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.grid.json', + template: createBufferSizeTemplate('named-no-buffer-size-grid-json-128', {}, {}), + assert: function (tile, callback) { + assert.utfgridEqualsFile(tile, this.fixturePath, 2, callback); + } + } + ]; + + testCases.forEach(function (test) { + it(test.desc, function (done) { + var testClient = new TestClient(test.template, 1234); + var coords = test.coords; + var options = { + format: test.format, + placeholders: test.placeholders, + layers: test.layers + }; + testClient.getTile(coords.z, coords.x, coords.y, options, function (err, res, tile) { + assert.ifError(err); + // To generate images use: + //tile.save(test.fixturePath); + // require('fs').writeFileSync(test.fixturePath, JSON.stringify(tile)); + // require('fs').writeFileSync(test.fixturePath, tile.getDataSync()); + test.assert(tile, function (err) { + assert.ifError(err); + testClient.drain(done); + }); + }); + }); + }); +}); diff --git a/test/fixtures/buffer-size/tile-7.64.48-buffer-size-0.png b/test/fixtures/buffer-size/tile-7.64.48-buffer-size-0.png new file mode 100644 index 00000000..798f7cca Binary files /dev/null and b/test/fixtures/buffer-size/tile-7.64.48-buffer-size-0.png differ diff --git a/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.geojson b/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.geojson new file mode 100644 index 00000000..e89c71dd --- /dev/null +++ b/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.geojson @@ -0,0 +1 @@ +{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53839,4629161]},"properties":{"name":"Alicante","cartodb_id":1200}},{"type":"Feature","geometry":{"type":"Point","coordinates":[242835,5069332]},"properties":{"name":"Barcelona","cartodb_id":5330}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-5567,4861644]},"properties":{"name":"Castello","cartodb_id":1201}},{"type":"Feature","geometry":{"type":"Point","coordinates":[272735,5092314]},"properties":{"name":"Mataro","cartodb_id":615}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-125787,4576600]},"properties":{"name":"Murcia","cartodb_id":952}},{"type":"Feature","geometry":{"type":"Point","coordinates":[295469,4804267]},"properties":{"name":"Palma","cartodb_id":5500}},{"type":"Feature","geometry":{"type":"Point","coordinates":[139148,5030112]},"properties":{"name":"Tarragona","cartodb_id":616}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-44746,4791667]},"properties":{"name":"Valencia","cartodb_id":5942}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-99072,5108695]},"properties":{"name":"Zaragoza","cartodb_id":5932}}]} \ No newline at end of file diff --git a/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.grid.json b/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.grid.json new file mode 100644 index 00000000..c06b8d91 --- /dev/null +++ b/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.grid.json @@ -0,0 +1 @@ +{"grid":[" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," !! ","!!! !!!!! ","!!!!!!! ! ","!!! !!!!! "," !! ! "," "," "," "," "," "," "," "," ### # "," ####### ###"," ####### ## ","$ ## #### ## ","$$ ","$$ ","$$ "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],"keys":["","9","2","1"],"data":{"1":{"cartodb_id":5942},"2":{"cartodb_id":5500},"9":{"cartodb_id":1201}}} \ No newline at end of file diff --git a/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.png b/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.png new file mode 100644 index 00000000..b3088d37 Binary files /dev/null and b/test/fixtures/buffer-size/tile-7.64.48-buffer-size-128.png differ diff --git a/test/fixtures/buffer-size/tile-grid.json.7.64.48-buffer-size-0.grid.json b/test/fixtures/buffer-size/tile-grid.json.7.64.48-buffer-size-0.grid.json new file mode 100644 index 00000000..24581bc3 --- /dev/null +++ b/test/fixtures/buffer-size/tile-grid.json.7.64.48-buffer-size-0.grid.json @@ -0,0 +1 @@ +{"grid":[" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," !!! ! "," !!!!!!! !!!"," !!!!!!! !! "," !! !!!! !! "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],"keys":["","1"],"data":{"1":{"cartodb_id":5500}}} \ No newline at end of file diff --git a/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-0.geojson b/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-0.geojson new file mode 100644 index 00000000..500fb3ea --- /dev/null +++ b/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-0.geojson @@ -0,0 +1 @@ +{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[295469,4804267]},"properties":{"name":"Palma","cartodb_id":5500}}]} \ No newline at end of file diff --git a/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-0.mvt b/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-0.mvt new file mode 100644 index 00000000..b87f1b9a Binary files /dev/null and b/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-0.mvt differ diff --git a/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-128.mvt b/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-128.mvt new file mode 100644 index 00000000..c6e54212 Binary files /dev/null and b/test/fixtures/buffer-size/tile-mvt-7.64.48-buffer-size-128.mvt differ diff --git a/test/support/test-client.js b/test/support/test-client.js index 75fa51e0..bbb32c9d 100644 --- a/test/support/test-client.js +++ b/test/support/test-client.js @@ -16,14 +16,23 @@ var serverOptions = require('../../lib/cartodb/server_options'); serverOptions.analysis.batch.inlineExecution = true; var server = new CartodbWindshaft(serverOptions); -function TestClient(mapConfig, apiKey) { - this.mapConfig = mapConfig; +function TestClient(config, apiKey) { + this.mapConfig = isMapConfig(config) ? config : null; + this.template = isTemplate(config) ? config : null; this.apiKey = apiKey; this.keysToDelete = {}; } module.exports = TestClient; +function isMapConfig(config) { + return config && config.layers; +} + +function isTemplate(config) { + return config && config.layergroup; +} + module.exports.RESPONSE = { ERROR: { status: 400, @@ -406,6 +415,7 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) { } var url = '/api/v1/map'; + var urlNamed = url + '/named'; if (this.apiKey) { url += '?' + qs.stringify({api_key: this.apiKey}); @@ -413,17 +423,60 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) { var layergroupId; step( - function createLayergroup() { + function createTemplate () { var next = this; + + if (!self.template) { + return next(); + } + + if (!self.apiKey) { + return next(new Error('apiKey param is mandatory to create a new template')); + } + + params.placeholders = params.placeholders || {}; + assert.response(server, { - url: url, + url: urlNamed + '?' + qs.stringify({ api_key: self.apiKey }), method: 'POST', headers: { host: 'localhost', 'Content-Type': 'application/json' }, - data: JSON.stringify(self.mapConfig) + data: JSON.stringify(self.template) + }, + { + status: 200, + headers: { + 'Content-Type': 'application/json; charset=utf-8' + } + }, + function (res, err) { + if (err) { + return next(err); + } + return next(null, JSON.parse(res.body).template_id); + } + ); + }, + function createLayergroup(err, templateId) { + var next = this; + + var data = templateId ? params.placeholders : self.mapConfig + var path = templateId ? + urlNamed + '/' + templateId + '?' + qs.stringify({api_key: self.apiKey}) : + url; + + assert.response(server, + { + url: path, + method: 'POST', + headers: { + host: 'localhost', + 'Content-Type': 'application/json' + }, + data: JSON.stringify(data) }, { status: 200, @@ -485,6 +538,27 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) { expectedResponse.headers['Content-Type'] = 'image/png'; } + var isMvt = format.match(/mvt$/); + + if (isMvt) { + request.encoding = 'binary'; + expectedResponse.headers['Content-Type'] = 'application/x-protobuf'; + } + + var isGeojson = format.match(/geojson$/); + + if (isGeojson) { + request.encoding = 'utf-8'; + expectedResponse.headers['Content-Type'] = 'application/json; charset=utf-8'; + } + + var isGridJSON = format.match(/grid.json$/); + + if (isGridJSON) { + request.encoding = 'utf-8'; + expectedResponse.headers['Content-Type'] = 'application/json; charset=utf-8'; + } + assert.response(server, request, expectedResponse, function(res, err) { assert.ifError(err); @@ -492,7 +566,12 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) { if (isPng) { obj = mapnik.Image.fromBytes(new Buffer(res.body, 'binary')); - } else { + } + else if (isMvt) { + obj = new mapnik.VectorTile(z, x, y); + obj.setDataSync(new Buffer(res.body, 'binary')); + } + else { obj = JSON.parse(res.body); } diff --git a/yarn.lock b/yarn.lock index de05fdf3..a203d58e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -abaculus@cartodb/abaculus#2.0.3-cdb1: +"abaculus@github:cartodb/abaculus#2.0.3-cdb1": version "2.0.3-cdb1" resolved "https://codeload.github.com/cartodb/abaculus/tar.gz/f5f34e1c80cdd8d49edd1d6fe3b2220ab2e23aaf" dependencies: @@ -22,8 +22,8 @@ accepts@~1.2.12: negotiator "0.5.3" ajv@^4.9.1: - version "4.11.7" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.7.tgz#8655a5d86d0824985cc471a1d913fb6729a0ec48" + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" @@ -205,7 +205,7 @@ camshaft@0.54.4: dot "^1.0.3" request "^2.69.0" -canvas@cartodb/node-canvas#1.6.2-cdb2: +"canvas@github:cartodb/node-canvas#1.6.2-cdb2": version "1.6.2-cdb2" resolved "https://codeload.github.com/cartodb/node-canvas/tar.gz/8acf04557005c633f9e68524488a2657c04f3766" dependencies: @@ -231,7 +231,7 @@ carto@CartoDB/carto#0.15.1-cdb1: optimist "~0.6.0" underscore "~1.6.0" -carto@cartodb/carto#0.15.1-cdb3: +"carto@github:cartodb/carto#0.15.1-cdb3": version "0.15.1-cdb3" resolved "https://codeload.github.com/cartodb/carto/tar.gz/945f5efb74fd1af1f5e1f69f409f9567f94fb5a7" dependencies: @@ -612,8 +612,8 @@ express@~4.13.3: vary "~1.0.1" extend@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" extsprintf@1.0.2: version "1.0.2" @@ -716,7 +716,7 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" -generic-pool@2.4.3: +generic-pool@2.4.3, generic-pool@~2.4.0, generic-pool@~2.4.1: version "2.4.3" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" @@ -728,17 +728,13 @@ generic-pool@~2.2.0, generic-pool@~2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.2.2.tgz#7a89f491d575b42f9f069a0e8e2c6dbaa3c241be" -generic-pool@~2.4.0, generic-pool@~2.4.1: - version "2.4.6" - resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.6.tgz#f1b55e572167dba2fe75d5aa91ebb1e9f72642d7" - get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" getpass@^0.1.1: - version "0.1.6" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" dependencies: assert-plus "^1.0.0" @@ -812,8 +808,8 @@ growl@1.8.1: resolved "https://registry.yarnpkg.com/growl/-/growl-1.8.1.tgz#4b2dec8d907e93db336624dcec0183502f8c9428" handlebars@^4.0.1: - version "4.0.6" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.6.tgz#2ce4484850537f9c97a8026d5399b935c4ed4ed7" + version "4.0.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.8.tgz#22b875cd3f0e6cbea30314f144e82bc7a72ff420" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -939,7 +935,7 @@ is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" -is-buffer@^1.0.2: +is-buffer@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" @@ -1084,10 +1080,10 @@ jsprim@^1.2.2: verror "1.3.6" kind-of@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" + version "3.2.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.0.tgz#b58abe4d5c044ad33726a8c1525b48cf891bff07" dependencies: - is-buffer "^1.0.2" + is-buffer "^1.1.5" lazy-cache@^1.0.3: version "1.0.4" @@ -1738,7 +1734,7 @@ repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" -request@2.x, request@^2.55.0, request@~2.79.0: +request@2.x, request@^2.55.0, request@^2.69.0, request@~2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" dependencies: @@ -1763,7 +1759,7 @@ request@2.x, request@^2.55.0, request@~2.79.0: tunnel-agent "~0.4.1" uuid "^3.0.0" -request@^2.69.0, request@^2.81.0: +request@^2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" dependencies: @@ -2098,17 +2094,17 @@ through@2: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" -tilelive-bridge@cartodb/tilelive-bridge#2.3.1-cdb1: - version "2.3.1-cdb1" - resolved "https://codeload.github.com/cartodb/tilelive-bridge/tar.gz/3f76c278c782e93d79045870387a0a06bace720b" +"tilelive-bridge@github:cartodb/tilelive-bridge#2.3.1-cdb2": + version "2.3.1-cdb2" + resolved "https://codeload.github.com/cartodb/tilelive-bridge/tar.gz/0346c634875ac87dbf8316cb81ac46d2c30fe313" dependencies: mapnik "~3.5.0" mapnik-pool "~0.1.3" sphericalmercator "1.0.x" -tilelive-mapnik@cartodb/tilelive-mapnik#0.6.18-cdb1: - version "0.6.18-cdb1" - resolved "https://codeload.github.com/cartodb/tilelive-mapnik/tar.gz/cf7e5b4633db653a889a6c6e6a5ddcbcf4ddc3b5" +"tilelive-mapnik@github:cartodb/tilelive-mapnik#0.6.18-cdb2": + version "0.6.18-cdb2" + resolved "https://codeload.github.com/cartodb/tilelive-mapnik/tar.gz/46f1adefee90f3f46c0ede5e0833f8522634a858" dependencies: generic-pool "~2.4.0" mapnik "3.5.14" @@ -2269,9 +2265,9 @@ window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" -windshaft@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/windshaft/-/windshaft-3.1.2.tgz#78c257bafe63c41df8cd7e4aa7ea6ea72ed1a5bd" +windshaft@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/windshaft/-/windshaft-3.2.0.tgz#c69f8d199bbeccc96e66b8256928e6fa87999803" dependencies: abaculus cartodb/abaculus#2.0.3-cdb1 canvas cartodb/node-canvas#1.6.2-cdb2 @@ -2288,8 +2284,8 @@ windshaft@3.1.2: sphericalmercator "1.0.4" step "~0.0.6" tilelive "5.12.2" - tilelive-bridge cartodb/tilelive-bridge#2.3.1-cdb1 - tilelive-mapnik cartodb/tilelive-mapnik#0.6.18-cdb1 + tilelive-bridge cartodb/tilelive-bridge#2.3.1-cdb2 + tilelive-mapnik cartodb/tilelive-mapnik#0.6.18-cdb2 torque.js "~2.11.0" underscore "~1.6.0"