2018-10-24 00:39:02 +08:00
|
|
|
'use strict';
|
|
|
|
|
2016-05-10 03:13:13 +08:00
|
|
|
var qs = require('querystring');
|
2019-10-07 16:44:45 +08:00
|
|
|
var testHelper = require('../support/test-helper');
|
2015-09-23 19:04:46 +08:00
|
|
|
var RedisPool = require('redis-mpool');
|
|
|
|
|
|
|
|
var assert = require('../support/assert');
|
|
|
|
var mapnik = require('windshaft').mapnik;
|
2019-10-07 15:40:50 +08:00
|
|
|
var CartodbWindshaft = require('../../lib/server');
|
2019-10-07 16:10:51 +08:00
|
|
|
var serverOptions = require('../../lib/server-options');
|
2019-10-07 16:50:14 +08:00
|
|
|
var TemplateMaps = require('../../lib/backends/template-maps');
|
2015-09-23 19:04:46 +08:00
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
describe('named maps static view', function () {
|
2015-09-23 19:04:46 +08:00
|
|
|
// configure redis pool instance to use in tests
|
|
|
|
var redisPool = new RedisPool(global.environment.redis);
|
|
|
|
|
|
|
|
var templateMaps = new TemplateMaps(redisPool, {
|
|
|
|
max_user_templates: global.environment.maxUserTemplates
|
|
|
|
});
|
|
|
|
|
|
|
|
var username = 'localhost';
|
|
|
|
var templateName = 'template_with_view';
|
|
|
|
|
2017-12-12 20:20:22 +08:00
|
|
|
var PNG_IMAGE_TOLERANCE = 20;
|
|
|
|
var JPG_IMAGE_TOLERANCE = 100;
|
2015-09-23 19:04:46 +08:00
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
function createTemplate (view, layers) {
|
2015-09-23 19:04:46 +08:00
|
|
|
return {
|
|
|
|
version: '0.0.1',
|
|
|
|
name: templateName,
|
|
|
|
auth: {
|
|
|
|
method: 'open'
|
|
|
|
},
|
|
|
|
placeholders: {
|
|
|
|
color: {
|
2019-10-22 01:07:24 +08:00
|
|
|
type: 'css_color',
|
|
|
|
default: '#cc3300'
|
2015-09-23 19:04:46 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
view: view,
|
|
|
|
layergroup: {
|
2017-03-31 02:09:38 +08:00
|
|
|
layers: layers || [
|
2015-09-23 19:04:46 +08:00
|
|
|
{
|
|
|
|
type: 'mapnik',
|
|
|
|
options: {
|
|
|
|
sql: 'select * from populated_places_simple_reduced',
|
|
|
|
cartocss: '#layer { marker-fill: <%= color %>; }',
|
|
|
|
cartocss_version: '2.3.0'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
afterEach(function (done) {
|
|
|
|
templateMaps.delTemplate(username, templateName, done);
|
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
function getStaticMap (params, callback) {
|
2016-05-10 03:13:13 +08:00
|
|
|
if (!callback) {
|
|
|
|
callback = params;
|
|
|
|
params = null;
|
|
|
|
}
|
2015-09-23 19:04:46 +08:00
|
|
|
|
|
|
|
var url = '/api/v1/map/static/named/' + templateName + '/640/480.png';
|
|
|
|
|
2016-05-10 03:13:13 +08:00
|
|
|
if (params !== null) {
|
|
|
|
url += '?' + qs.stringify(params);
|
|
|
|
}
|
|
|
|
|
2015-09-23 19:04:46 +08:00
|
|
|
var requestOptions = {
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: username
|
|
|
|
},
|
|
|
|
encoding: 'binary'
|
|
|
|
};
|
|
|
|
|
|
|
|
var expectedResponse = {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'image/png'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// this could be removed once named maps are invalidated, otherwise you hits the cache
|
|
|
|
var server = new CartodbWindshaft(serverOptions);
|
|
|
|
|
|
|
|
assert.response(server, requestOptions, expectedResponse, function (res, err) {
|
2019-10-22 01:07:24 +08:00
|
|
|
testHelper.deleteRedisKeys({ 'user:localhost:mapviews:global': 5 }, function () {
|
2015-09-29 18:21:11 +08:00
|
|
|
return callback(err, mapnik.Image.fromBytes(new Buffer(res.body, 'binary')));
|
|
|
|
});
|
2015-09-23 19:04:46 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
function previewFixture (version, format = 'png') {
|
2017-12-12 20:20:22 +08:00
|
|
|
return './test/fixtures/previews/populated_places_simple_reduced-' + version + '.' + format;
|
2015-09-23 19:04:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
it('should return an image estimating its bounds based on dataset', function (done) {
|
|
|
|
templateMaps.addTemplate(username, createTemplate(), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2019-10-22 01:07:24 +08:00
|
|
|
getStaticMap(function (err, img) {
|
2015-09-23 19:04:46 +08:00
|
|
|
assert.ok(!err);
|
2019-10-22 01:07:24 +08:00
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('estimated'), PNG_IMAGE_TOLERANCE, err => {
|
2019-04-10 19:06:39 +08:00
|
|
|
if (err) {
|
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('estimated-proj5'), PNG_IMAGE_TOLERANCE, done);
|
2019-10-22 01:07:24 +08:00
|
|
|
} else {
|
2019-04-10 19:06:39 +08:00
|
|
|
done();
|
|
|
|
}
|
|
|
|
});
|
2015-09-23 19:04:46 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return an image using view zoom + center', function (done) {
|
|
|
|
var view = {
|
|
|
|
zoom: 4,
|
|
|
|
center: {
|
|
|
|
lng: 40,
|
|
|
|
lat: 20
|
|
|
|
}
|
|
|
|
};
|
|
|
|
templateMaps.addTemplate(username, createTemplate(view), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2019-10-22 01:07:24 +08:00
|
|
|
getStaticMap(function (err, img) {
|
2015-09-23 19:04:46 +08:00
|
|
|
assert.ok(!err);
|
2017-12-12 20:20:22 +08:00
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('zoom-center'), PNG_IMAGE_TOLERANCE, done);
|
2015-09-23 19:04:46 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return an image using view bounds', function (done) {
|
|
|
|
var view = {
|
|
|
|
bounds: {
|
|
|
|
west: 0,
|
|
|
|
south: 0,
|
|
|
|
east: 45,
|
|
|
|
north: 45
|
|
|
|
}
|
|
|
|
};
|
|
|
|
templateMaps.addTemplate(username, createTemplate(view), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2019-10-22 01:07:24 +08:00
|
|
|
getStaticMap(function (err, img) {
|
2015-09-23 19:04:46 +08:00
|
|
|
assert.ok(!err);
|
2017-12-12 20:20:22 +08:00
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('bounds'), PNG_IMAGE_TOLERANCE, done);
|
2015-09-23 19:04:46 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return an image using view zoom + center when bounds are also present', function (done) {
|
|
|
|
var view = {
|
|
|
|
bounds: {
|
|
|
|
west: 0,
|
|
|
|
south: 0,
|
|
|
|
east: 45,
|
|
|
|
north: 45
|
|
|
|
},
|
|
|
|
zoom: 4,
|
|
|
|
center: {
|
|
|
|
lng: 40,
|
|
|
|
lat: 20
|
|
|
|
}
|
|
|
|
};
|
|
|
|
templateMaps.addTemplate(username, createTemplate(view), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2019-10-22 01:07:24 +08:00
|
|
|
getStaticMap(function (err, img) {
|
2015-09-23 19:04:46 +08:00
|
|
|
assert.ok(!err);
|
2017-12-12 20:20:22 +08:00
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('zoom-center'), PNG_IMAGE_TOLERANCE, done);
|
2015-09-23 19:04:46 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-05-10 03:13:13 +08:00
|
|
|
it('should return override zoom', function (done) {
|
|
|
|
var view = {
|
|
|
|
bounds: {
|
|
|
|
west: 0,
|
|
|
|
south: 0,
|
|
|
|
east: 45,
|
|
|
|
north: 45
|
|
|
|
},
|
|
|
|
zoom: 4,
|
|
|
|
center: {
|
|
|
|
lng: 40,
|
|
|
|
lat: 20
|
|
|
|
}
|
|
|
|
};
|
|
|
|
templateMaps.addTemplate(username, createTemplate(view), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2019-10-22 01:07:24 +08:00
|
|
|
getStaticMap({ zoom: 3 }, function (err, img) {
|
2016-05-10 03:13:13 +08:00
|
|
|
assert.ok(!err);
|
2017-12-12 20:20:22 +08:00
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('override-zoom'), PNG_IMAGE_TOLERANCE, done);
|
2017-08-29 21:04:20 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return override bbox', function (done) {
|
|
|
|
var view = {
|
|
|
|
bounds: {
|
|
|
|
west: 0,
|
|
|
|
south: 0,
|
|
|
|
east: 45,
|
|
|
|
north: 45
|
|
|
|
},
|
|
|
|
zoom: 4,
|
|
|
|
center: {
|
|
|
|
lng: 40,
|
|
|
|
lat: 20
|
|
|
|
}
|
|
|
|
};
|
|
|
|
templateMaps.addTemplate(username, createTemplate(view), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2019-10-22 01:07:24 +08:00
|
|
|
getStaticMap({ bbox: '0,45,90,45' }, function (err, img) {
|
2017-08-29 21:04:20 +08:00
|
|
|
assert.ok(!err);
|
2017-12-12 20:20:22 +08:00
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('override-bbox'), PNG_IMAGE_TOLERANCE, done);
|
2016-05-10 03:13:13 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-03-31 02:09:38 +08:00
|
|
|
it('should allow to select the layers to render', function (done) {
|
|
|
|
var view = {
|
|
|
|
bounds: {
|
|
|
|
west: 0,
|
|
|
|
south: 0,
|
|
|
|
east: 45,
|
|
|
|
north: 45
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var layers = [
|
|
|
|
{
|
|
|
|
type: 'mapnik',
|
|
|
|
options: {
|
|
|
|
sql: 'select * from populated_places_simple_reduced',
|
|
|
|
cartocss: '#layer { marker-fill: <%= color %>; }',
|
|
|
|
cartocss_version: '2.3.0'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'mapnik',
|
|
|
|
options: {
|
|
|
|
sql: 'select ST_Transform(ST_MakeEnvelope(-45, -45, 45, 45, 4326), 3857) the_geom_webmercator',
|
|
|
|
cartocss: '#layer { polygon-fill: <%= color %>; }',
|
|
|
|
cartocss_version: '2.3.0'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
];
|
|
|
|
templateMaps.addTemplate(username, createTemplate(view, layers), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2019-10-22 01:07:24 +08:00
|
|
|
getStaticMap({ layer: 0 }, function (err, img) {
|
2017-03-31 02:09:38 +08:00
|
|
|
assert.ok(!err);
|
2017-12-12 20:20:22 +08:00
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('bounds'), PNG_IMAGE_TOLERANCE, done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return jpg static map', function (done) {
|
|
|
|
var view = {
|
|
|
|
zoom: 4,
|
|
|
|
center: {
|
|
|
|
lng: 40,
|
|
|
|
lat: 20
|
|
|
|
}
|
|
|
|
};
|
|
|
|
templateMaps.addTemplate(username, createTemplate(view), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2019-10-22 01:07:24 +08:00
|
|
|
getStaticMap({ format: 'jpeg' }, function (err, img) {
|
2017-12-12 20:20:22 +08:00
|
|
|
assert.ok(!err);
|
|
|
|
assert.imageIsSimilarToFile(img, previewFixture('zoom-center', 'jpeg'),
|
2019-10-22 01:07:24 +08:00
|
|
|
JPG_IMAGE_TOLERANCE, done, 'jpeg');
|
2017-03-31 02:09:38 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-05-11 23:41:26 +08:00
|
|
|
it('should return an error requesting unsupported image format', function (done) {
|
|
|
|
var view = {
|
|
|
|
zoom: 4,
|
|
|
|
center: {
|
|
|
|
lng: 40,
|
|
|
|
lat: 20
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
templateMaps.addTemplate(username, createTemplate(view), function (err) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2018-10-24 00:39:02 +08:00
|
|
|
|
2018-05-11 23:41:26 +08:00
|
|
|
var url = `/api/v1/map/static/named/${templateName}/640/480.gif`;
|
|
|
|
|
|
|
|
var requestOptions = {
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: username
|
|
|
|
},
|
|
|
|
encoding: 'binary'
|
|
|
|
};
|
|
|
|
|
|
|
|
var expectedResponse = {
|
|
|
|
status: 400,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// this could be removed once named maps are invalidated, otherwise you hits the cache
|
|
|
|
var server = new CartodbWindshaft(serverOptions);
|
|
|
|
|
|
|
|
assert.response(server, requestOptions, expectedResponse, function (res, err) {
|
|
|
|
assert.ifError(err);
|
2019-10-22 01:52:51 +08:00
|
|
|
assert.deepStrictEqual(
|
2018-05-11 23:41:26 +08:00
|
|
|
JSON.parse(res.body),
|
|
|
|
{
|
2019-10-22 01:07:24 +08:00
|
|
|
errors: ['Unsupported image format \"gif\"'],
|
|
|
|
errors_with_context: [{
|
2018-05-11 23:41:26 +08:00
|
|
|
type: 'unknown',
|
|
|
|
message: 'Unsupported image format \"gif\"'
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2015-09-23 19:04:46 +08:00
|
|
|
});
|