2016-02-05 19:59:33 +08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var qs = require('querystring');
|
|
|
|
var step = require('step');
|
2016-05-05 23:52:37 +08:00
|
|
|
var urlParser = require('url');
|
2017-07-26 01:15:43 +08:00
|
|
|
var PSQL = require('cartodb-psql');
|
|
|
|
var _ = require('underscore');
|
2016-03-02 19:40:53 +08:00
|
|
|
var mapnik = require('windshaft').mapnik;
|
|
|
|
|
2017-08-04 23:51:10 +08:00
|
|
|
var LayergroupToken = require('../../lib/cartodb/models/layergroup-token');
|
2016-02-05 19:59:33 +08:00
|
|
|
|
|
|
|
var assert = require('./assert');
|
|
|
|
var helper = require('./test_helper');
|
|
|
|
|
|
|
|
var CartodbWindshaft = require('../../lib/cartodb/server');
|
|
|
|
var serverOptions = require('../../lib/cartodb/server_options');
|
2016-04-14 23:25:08 +08:00
|
|
|
serverOptions.analysis.batch.inlineExecution = true;
|
2016-02-05 19:59:33 +08:00
|
|
|
|
2017-07-27 00:35:40 +08:00
|
|
|
const MAPNIK_SUPPORTED_FORMATS = {
|
|
|
|
'png': true,
|
|
|
|
'png32': true,
|
|
|
|
'grid.json': true,
|
|
|
|
'mvt': true
|
2017-10-06 21:24:58 +08:00
|
|
|
};
|
2017-07-27 00:35:40 +08:00
|
|
|
|
2017-04-27 00:27:18 +08:00
|
|
|
function TestClient(config, apiKey) {
|
|
|
|
this.mapConfig = isMapConfig(config) ? config : null;
|
|
|
|
this.template = isTemplate(config) ? config : null;
|
2016-03-02 19:40:53 +08:00
|
|
|
this.apiKey = apiKey;
|
2016-02-05 19:59:33 +08:00
|
|
|
this.keysToDelete = {};
|
2017-07-19 02:50:31 +08:00
|
|
|
this.server = new CartodbWindshaft(serverOptions);
|
2016-02-05 19:59:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = TestClient;
|
|
|
|
|
2017-04-27 00:27:18 +08:00
|
|
|
function isMapConfig(config) {
|
|
|
|
return config && config.layers;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isTemplate(config) {
|
|
|
|
return config && config.layergroup;
|
|
|
|
}
|
|
|
|
|
2016-06-21 18:08:40 +08:00
|
|
|
module.exports.RESPONSE = {
|
|
|
|
ERROR: {
|
|
|
|
status: 400,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-06-29 22:07:42 +08:00
|
|
|
module.exports.CARTOCSS = {
|
|
|
|
POINTS: [
|
|
|
|
'#layer{',
|
|
|
|
' marker-placement: point;',
|
|
|
|
' marker-allow-overlap: true;',
|
|
|
|
' marker-line-opacity: 0.2;',
|
|
|
|
' marker-line-width: 0.5;',
|
|
|
|
' marker-opacity: 1;',
|
|
|
|
' marker-width: 5;',
|
|
|
|
' marker-fill: red;',
|
|
|
|
'}'
|
|
|
|
].join('\n'),
|
|
|
|
|
|
|
|
LINES: [
|
|
|
|
'#lines {',
|
|
|
|
' line-color: black;',
|
|
|
|
' line-width: 1;',
|
|
|
|
' line-opacity: 1;',
|
|
|
|
'}'
|
|
|
|
].join('\n'),
|
|
|
|
|
|
|
|
POLYGONS: [
|
|
|
|
'#layer {',
|
|
|
|
' polygon-fill: red;',
|
|
|
|
' polygon-opacity: 0.6;',
|
|
|
|
' polygon-opacity: 0.7;',
|
|
|
|
' line-color: #FFF;',
|
|
|
|
' line-width: 0.5;',
|
|
|
|
' line-opacity: 1;',
|
|
|
|
'}'
|
2017-07-26 01:15:43 +08:00
|
|
|
].join('\n'),
|
|
|
|
|
|
|
|
TORQUE: [
|
|
|
|
'Map {',
|
|
|
|
' -torque-frame-count: 256;',
|
|
|
|
' -torque-animation-duration: 30;',
|
|
|
|
' -torque-time-attribute: "cartodb_id";',
|
|
|
|
' -torque-aggregation-function: "count(1)";',
|
|
|
|
' -torque-resolution: 4;',
|
|
|
|
' -torque-data-aggregation: linear;',
|
|
|
|
'}',
|
|
|
|
'#layer {',
|
|
|
|
' marker-width: 7;',
|
|
|
|
' marker-fill: #FFB927;',
|
|
|
|
' marker-fill-opacity: 0.9;',
|
|
|
|
' marker-line-width: 1;',
|
|
|
|
' marker-line-color: #FFF;',
|
|
|
|
' marker-line-opacity: 1;',
|
|
|
|
' comp-op: lighter;',
|
|
|
|
'}',
|
|
|
|
'#layer[frame-offset=1] {',
|
|
|
|
' marker-width: 9;',
|
|
|
|
' marker-fill-opacity: 0.45;',
|
|
|
|
'}',
|
|
|
|
'#layer[frame-offset=2] {',
|
|
|
|
' marker-width: 11;',
|
|
|
|
' marker-fill-opacity: 0.225;',
|
|
|
|
'}'
|
2016-06-29 22:07:42 +08:00
|
|
|
].join('\n')
|
|
|
|
};
|
|
|
|
|
2017-07-18 16:44:27 +08:00
|
|
|
module.exports.SQL = {
|
|
|
|
EMPTY: 'select 1 as cartodb_id, null::geometry as the_geom_webmercator',
|
|
|
|
ONE_POINT: 'select 1 as cartodb_id, \'SRID=3857;POINT(0 0)\'::geometry the_geom_webmercator'
|
2017-10-06 21:24:58 +08:00
|
|
|
};
|
2017-07-18 16:44:27 +08:00
|
|
|
|
2017-10-09 23:51:42 +08:00
|
|
|
function resErr2errRes(callback) {
|
|
|
|
return (res, err) => {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
return callback(err, res);
|
|
|
|
};
|
2017-07-18 16:44:27 +08:00
|
|
|
}
|
|
|
|
|
2018-05-23 00:27:50 +08:00
|
|
|
function layergroupidTemplate (layergroupId, params) {
|
|
|
|
const { token, signer, cacheBuster } = LayergroupToken.parse(layergroupId);
|
|
|
|
|
|
|
|
// {user}@{token}:{cache_buster}
|
|
|
|
// {token}:{cache_buster}
|
|
|
|
return `${signer ? signer + '@' : ''}${token}:${params.cacheBuster ? Date.now() : cacheBuster }`;
|
|
|
|
}
|
|
|
|
|
2016-02-05 19:59:33 +08:00
|
|
|
TestClient.prototype.getWidget = function(widgetName, params, callback) {
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
if (!callback) {
|
|
|
|
callback = params;
|
|
|
|
params = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
|
|
|
if (params && params.filters) {
|
|
|
|
url += '?' + qs.stringify({ filters: JSON.stringify(params.filters) });
|
|
|
|
}
|
|
|
|
|
|
|
|
step(
|
|
|
|
function createLayergroup() {
|
|
|
|
var next = this;
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-02-05 19:59:33 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(self.mapConfig)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
2016-05-27 01:32:58 +08:00
|
|
|
|
2016-02-05 19:59:33 +08:00
|
|
|
var expectedWidgetURLS = {
|
|
|
|
http: "/api/v1/map/" + parsedBody.layergroupid + "/0/widget/" + widgetName
|
|
|
|
};
|
|
|
|
assert.ok(parsedBody.metadata.layers[0].widgets[widgetName]);
|
|
|
|
assert.ok(
|
|
|
|
parsedBody.metadata.layers[0].widgets[widgetName].url.http.match(expectedWidgetURLS.http)
|
|
|
|
);
|
2016-05-27 01:32:58 +08:00
|
|
|
|
|
|
|
var expectedDataviewsURLS = {
|
|
|
|
http: "/api/v1/map/" + parsedBody.layergroupid + "/dataview/" + widgetName
|
|
|
|
};
|
|
|
|
assert.ok(parsedBody.metadata.dataviews[widgetName]);
|
|
|
|
assert.ok(
|
|
|
|
parsedBody.metadata.dataviews[widgetName].url.http.match(expectedDataviewsURLS.http)
|
|
|
|
);
|
|
|
|
|
2016-02-05 19:59:33 +08:00
|
|
|
return next(null, parsedBody.layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2017-10-06 21:27:03 +08:00
|
|
|
function getWidgetResult(err, layergroupId) {
|
2016-02-05 19:59:33 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
|
|
|
var next = this;
|
2017-10-06 21:27:03 +08:00
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
2016-02-05 19:59:33 +08:00
|
|
|
|
|
|
|
var urlParams = {
|
|
|
|
own_filter: params.hasOwnProperty('own_filter') ? params.own_filter : 1
|
|
|
|
};
|
2016-06-01 21:00:30 +08:00
|
|
|
['bbox', 'bins', 'start', 'end'].forEach(function(extraParam) {
|
|
|
|
if (params.hasOwnProperty(extraParam)) {
|
|
|
|
urlParams[extraParam] = params[extraParam];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-02-05 19:59:33 +08:00
|
|
|
url = '/api/v1/map/' + layergroupId + '/0/widget/' + widgetName + '?' + qs.stringify(urlParams);
|
|
|
|
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-02-05 19:59:33 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
next(null, res);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function finish(err, res) {
|
2016-06-01 00:20:16 +08:00
|
|
|
var widget;
|
|
|
|
if (!err && res.body) {
|
|
|
|
widget = JSON.parse(res.body);
|
|
|
|
}
|
|
|
|
return callback(err, res, widget);
|
2016-02-05 19:59:33 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2016-06-01 17:43:04 +08:00
|
|
|
TestClient.prototype.widgetSearch = function(widgetName, userQuery, params, callback) {
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
if (!callback) {
|
|
|
|
callback = params;
|
|
|
|
params = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
|
|
|
if (params && params.filters) {
|
|
|
|
url += '?' + qs.stringify({ filters: JSON.stringify(params.filters) });
|
|
|
|
}
|
|
|
|
|
|
|
|
step(
|
|
|
|
function createLayergroup() {
|
|
|
|
var next = this;
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-06-01 17:43:04 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(self.mapConfig)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
|
|
|
|
var expectedWidgetURLS = {
|
|
|
|
http: "/api/v1/map/" + parsedBody.layergroupid + "/0/widget/" + widgetName
|
|
|
|
};
|
|
|
|
assert.ok(parsedBody.metadata.layers[0].widgets[widgetName]);
|
|
|
|
assert.ok(
|
|
|
|
parsedBody.metadata.layers[0].widgets[widgetName].url.http.match(expectedWidgetURLS.http)
|
|
|
|
);
|
|
|
|
|
|
|
|
var expectedDataviewsURLS = {
|
|
|
|
http: "/api/v1/map/" + parsedBody.layergroupid + "/dataview/" + widgetName
|
|
|
|
};
|
|
|
|
assert.ok(parsedBody.metadata.dataviews[widgetName]);
|
|
|
|
assert.ok(
|
|
|
|
parsedBody.metadata.dataviews[widgetName].url.http.match(expectedDataviewsURLS.http)
|
|
|
|
);
|
|
|
|
|
|
|
|
return next(null, parsedBody.layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2017-10-06 21:27:03 +08:00
|
|
|
function getWidgetSearchResult(err, layergroupId) {
|
2016-06-01 17:43:04 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
|
|
|
var next = this;
|
2017-10-06 21:27:03 +08:00
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
2016-06-01 17:43:04 +08:00
|
|
|
|
|
|
|
var urlParams = {
|
|
|
|
q: userQuery,
|
|
|
|
own_filter: params.hasOwnProperty('own_filter') ? params.own_filter : 1
|
|
|
|
};
|
|
|
|
if (params && params.bbox) {
|
|
|
|
urlParams.bbox = params.bbox;
|
|
|
|
}
|
|
|
|
url = '/api/v1/map/' + layergroupId + '/0/widget/' + widgetName + '/search?' + qs.stringify(urlParams);
|
|
|
|
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-06-01 17:43:04 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
next(null, res);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function finish(err, res) {
|
|
|
|
var searchResult;
|
|
|
|
if (!err && res.body) {
|
|
|
|
searchResult = JSON.parse(res.body);
|
|
|
|
}
|
|
|
|
return callback(err, res, searchResult);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2016-03-19 00:22:02 +08:00
|
|
|
TestClient.prototype.getDataview = function(dataviewName, params, callback) {
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
if (!callback) {
|
|
|
|
callback = params;
|
|
|
|
params = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
var extraParams = {};
|
|
|
|
if (this.apiKey) {
|
|
|
|
extraParams.api_key = this.apiKey;
|
|
|
|
}
|
|
|
|
if (params && params.filters) {
|
|
|
|
extraParams.filters = JSON.stringify(params.filters);
|
|
|
|
}
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
2018-04-13 01:58:33 +08:00
|
|
|
var urlNamed = url + '/named';
|
|
|
|
|
2016-03-19 00:22:02 +08:00
|
|
|
if (Object.keys(extraParams).length > 0) {
|
|
|
|
url += '?' + qs.stringify(extraParams);
|
|
|
|
}
|
|
|
|
|
2017-02-02 23:12:49 +08:00
|
|
|
var expectedResponse = params.response || {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-03-19 00:22:02 +08:00
|
|
|
step(
|
2018-04-13 01:58:33 +08:00
|
|
|
function createTemplate () {
|
2016-03-19 00:22:02 +08:00
|
|
|
var next = this;
|
2018-04-13 01:58:33 +08:00
|
|
|
|
|
|
|
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 || {};
|
|
|
|
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-03-19 00:22:02 +08:00
|
|
|
{
|
2018-04-13 01:58:33 +08:00
|
|
|
url: urlNamed + '?' + qs.stringify({ api_key: self.apiKey }),
|
2016-03-19 00:22:02 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
2018-04-13 01:58:33 +08:00
|
|
|
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) {
|
|
|
|
assert.ifError(err);
|
|
|
|
|
|
|
|
var next = this;
|
|
|
|
|
|
|
|
var data = templateId ? params.placeholders : self.mapConfig;
|
|
|
|
|
|
|
|
const queryParams = {};
|
|
|
|
|
|
|
|
if (self.apiKey) {
|
|
|
|
queryParams.api_key = self.apiKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (params.filters !== undefined) {
|
|
|
|
queryParams.filters = JSON.stringify(params.filters);
|
|
|
|
}
|
|
|
|
|
|
|
|
var path = templateId ?
|
|
|
|
urlNamed + '/' + templateId + '?' + qs.stringify(queryParams) :
|
|
|
|
url;
|
|
|
|
|
|
|
|
assert.response(self.server,
|
|
|
|
{
|
|
|
|
url: path,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(data)
|
2016-03-19 00:22:02 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
2016-03-19 01:09:17 +08:00
|
|
|
var expectedDataviewsURLS = {
|
|
|
|
http: "/api/v1/map/" + parsedBody.layergroupid + "/dataview/" + dataviewName
|
|
|
|
};
|
|
|
|
assert.ok(parsedBody.metadata.dataviews[dataviewName]);
|
|
|
|
assert.ok(
|
|
|
|
parsedBody.metadata.dataviews[dataviewName].url.http.match(expectedDataviewsURLS.http)
|
|
|
|
);
|
2016-03-19 00:22:02 +08:00
|
|
|
return next(null, parsedBody.layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2017-10-06 21:27:03 +08:00
|
|
|
function getDataviewResult(err, layergroupId) {
|
2016-03-19 00:22:02 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
|
|
|
var next = this;
|
2017-10-06 20:41:50 +08:00
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
2016-03-19 00:22:02 +08:00
|
|
|
|
2017-12-12 22:56:16 +08:00
|
|
|
var urlParams = {};
|
|
|
|
if (params.hasOwnProperty('no_filters')) {
|
|
|
|
urlParams.no_filters = params.no_filters;
|
2018-03-03 01:22:53 +08:00
|
|
|
}
|
2017-12-13 17:43:43 +08:00
|
|
|
if (params.hasOwnProperty('own_filter')) {
|
|
|
|
urlParams.own_filter = params.own_filter;
|
2017-12-12 22:56:16 +08:00
|
|
|
}
|
2016-06-06 23:10:36 +08:00
|
|
|
|
2017-11-07 23:14:47 +08:00
|
|
|
['bbox', 'bins', 'start', 'end', 'aggregation', 'offset', 'categories'].forEach(function(extraParam) {
|
2016-06-06 23:10:36 +08:00
|
|
|
if (params.hasOwnProperty(extraParam)) {
|
|
|
|
urlParams[extraParam] = params[extraParam];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-03-19 00:22:02 +08:00
|
|
|
if (self.apiKey) {
|
|
|
|
urlParams.api_key = self.apiKey;
|
|
|
|
}
|
|
|
|
url = '/api/v1/map/' + layergroupId + '/dataview/' + dataviewName + '?' + qs.stringify(urlParams);
|
|
|
|
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-03-19 00:22:02 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
},
|
2017-02-02 23:12:49 +08:00
|
|
|
expectedResponse,
|
2016-03-19 00:22:02 +08:00
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
2018-08-30 00:00:13 +08:00
|
|
|
next(null, JSON.parse(res.body), res.headers);
|
2016-03-19 00:22:02 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2018-08-30 00:00:13 +08:00
|
|
|
function finish(err, dataview, headers = null) {
|
2017-07-27 18:46:38 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
2018-08-30 00:00:13 +08:00
|
|
|
return callback(null, dataview, headers);
|
2016-03-19 00:22:02 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2017-06-27 17:21:05 +08:00
|
|
|
TestClient.prototype.getFeatureAttributes = function(featureId, layerId, params, callback) {
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
if (!callback) {
|
|
|
|
callback = params;
|
|
|
|
params = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
var extraParams = {};
|
|
|
|
if (this.apiKey) {
|
|
|
|
extraParams.api_key = this.apiKey;
|
|
|
|
}
|
|
|
|
if (params && params.filters) {
|
|
|
|
extraParams.filters = JSON.stringify(params.filters);
|
|
|
|
}
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
|
|
|
if (Object.keys(extraParams).length > 0) {
|
|
|
|
url += '?' + qs.stringify(extraParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
var expectedResponse = params.response || {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
step(
|
|
|
|
function createLayergroup() {
|
|
|
|
var next = this;
|
2017-08-10 22:24:40 +08:00
|
|
|
assert.response(self.server,
|
2017-06-27 17:21:05 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(self.mapConfig)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
|
|
|
|
if (parsedBody.layergroupid) {
|
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0;
|
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
return next(null, parsedBody.layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function getFeatureAttributes(err, layergroupId) {
|
|
|
|
assert.ifError(err);
|
|
|
|
|
|
|
|
var next = this;
|
|
|
|
|
|
|
|
url = '/api/v1/map/' + layergroupId + '/' + layerId + '/attributes/' + featureId;
|
|
|
|
|
2019-02-27 02:19:44 +08:00
|
|
|
assert.response(self.server,
|
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
expectedResponse,
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
next(null, JSON.parse(res.body));
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function finish(err, attributes) {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(null, attributes);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2019-02-27 19:43:26 +08:00
|
|
|
TestClient.prototype.getClusterFeatures = function (zoom, clusterId, layerId, params, callback) {
|
2019-02-27 02:19:44 +08:00
|
|
|
var self = this;
|
|
|
|
|
|
|
|
if (!callback) {
|
|
|
|
callback = params;
|
|
|
|
params = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
var extraParams = {};
|
|
|
|
|
|
|
|
if (this.apiKey) {
|
|
|
|
extraParams.api_key = this.apiKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if (params && params.filters) {
|
|
|
|
// extraParams.filters = JSON.stringify(params.filters);
|
|
|
|
// }
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
|
|
|
if (Object.keys(extraParams).length > 0) {
|
|
|
|
url += '?' + qs.stringify(extraParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
var expectedResponse = params.response || {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
step(
|
|
|
|
function createLayergroup() {
|
|
|
|
var next = this;
|
|
|
|
assert.response(self.server,
|
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(self.mapConfig)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
|
|
|
|
if (parsedBody.layergroupid) {
|
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0;
|
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
return next(null, parsedBody.layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2019-02-27 19:43:26 +08:00
|
|
|
function getCLusterFeatures (err, layergroupId) {
|
2019-02-27 02:19:44 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
|
|
|
var next = this;
|
|
|
|
|
2019-02-27 19:43:26 +08:00
|
|
|
url = '/api/v1/map/' + layergroupId + '/' + layerId + '/' + zoom + '/cluster/' + clusterId;
|
2019-02-27 02:19:44 +08:00
|
|
|
|
2017-08-10 22:24:40 +08:00
|
|
|
assert.response(self.server,
|
2017-06-27 17:21:05 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
expectedResponse,
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
next(null, JSON.parse(res.body));
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function finish(err, attributes) {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(null, attributes);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2016-03-02 19:40:53 +08:00
|
|
|
TestClient.prototype.getTile = function(z, x, y, params, callback) {
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
if (!callback) {
|
|
|
|
callback = params;
|
|
|
|
params = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
2017-04-27 00:27:18 +08:00
|
|
|
var urlNamed = url + '/named';
|
2016-03-02 19:40:53 +08:00
|
|
|
|
|
|
|
if (this.apiKey) {
|
|
|
|
url += '?' + qs.stringify({api_key: this.apiKey});
|
|
|
|
}
|
|
|
|
|
|
|
|
var layergroupId;
|
2017-08-01 00:14:32 +08:00
|
|
|
|
|
|
|
if (params.layergroupid) {
|
2017-10-06 21:24:58 +08:00
|
|
|
layergroupId = params.layergroupid;
|
2017-08-01 00:14:32 +08:00
|
|
|
}
|
|
|
|
|
2016-03-02 19:40:53 +08:00
|
|
|
step(
|
2017-04-27 00:27:18 +08:00
|
|
|
function createTemplate () {
|
2016-03-02 19:40:53 +08:00
|
|
|
var next = this;
|
2017-04-27 00:27:18 +08:00
|
|
|
|
|
|
|
if (!self.template) {
|
|
|
|
return next();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!self.apiKey) {
|
|
|
|
return next(new Error('apiKey param is mandatory to create a new template'));
|
|
|
|
}
|
|
|
|
|
2017-10-06 21:24:58 +08:00
|
|
|
params.placeholders = params.placeholders || {};
|
2017-06-22 00:44:21 +08:00
|
|
|
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-03-02 19:40:53 +08:00
|
|
|
{
|
2017-04-27 00:27:18 +08:00
|
|
|
url: urlNamed + '?' + qs.stringify({ api_key: self.apiKey }),
|
2016-03-02 19:40:53 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
2017-04-27 00:27:18 +08:00
|
|
|
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;
|
|
|
|
|
2017-08-01 00:14:32 +08:00
|
|
|
if (layergroupId) {
|
|
|
|
return next(null, layergroupId);
|
|
|
|
}
|
|
|
|
|
2017-10-06 21:24:58 +08:00
|
|
|
var data = templateId ? params.placeholders : self.mapConfig;
|
2017-12-05 19:09:31 +08:00
|
|
|
|
|
|
|
const queryParams = {};
|
|
|
|
|
|
|
|
if (self.apiKey) {
|
|
|
|
queryParams.api_key = self.apiKey;
|
|
|
|
}
|
|
|
|
|
2017-12-13 02:23:21 +08:00
|
|
|
if (params.aggregation !== undefined) {
|
2017-12-05 19:09:31 +08:00
|
|
|
queryParams.aggregation = params.aggregation;
|
|
|
|
}
|
|
|
|
|
2017-04-27 00:27:18 +08:00
|
|
|
var path = templateId ?
|
2017-12-05 19:09:31 +08:00
|
|
|
urlNamed + '/' + templateId + '?' + qs.stringify(queryParams) :
|
2017-04-27 00:27:18 +08:00
|
|
|
url;
|
|
|
|
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2017-04-27 00:27:18 +08:00
|
|
|
{
|
|
|
|
url: path,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(data)
|
2016-03-02 19:40:53 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
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).layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2017-10-06 21:27:03 +08:00
|
|
|
function getTileResult(err, layergroupId) {
|
2017-12-05 19:09:31 +08:00
|
|
|
// jshint maxcomplexity:13
|
2016-03-02 19:40:53 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
2017-10-06 20:41:50 +08:00
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
2016-03-02 19:40:53 +08:00
|
|
|
|
2018-05-23 00:27:50 +08:00
|
|
|
url = `/api/v1/map/${layergroupidTemplate(layergroupId, params)}/`;
|
2016-03-02 19:40:53 +08:00
|
|
|
|
|
|
|
var layers = params.layers;
|
2016-03-09 03:06:43 +08:00
|
|
|
|
|
|
|
if (layers !== undefined) {
|
2016-03-02 19:40:53 +08:00
|
|
|
layers = Array.isArray(layers) ? layers : [layers];
|
|
|
|
url += layers.join(',') + '/';
|
|
|
|
}
|
|
|
|
|
|
|
|
var format = params.format || 'png';
|
|
|
|
|
2017-07-27 00:35:40 +08:00
|
|
|
if (layers === undefined && !MAPNIK_SUPPORTED_FORMATS[format]) {
|
|
|
|
throw new Error(`Missing layer filter while fetching ${format} tile, review params argument`);
|
|
|
|
}
|
|
|
|
|
2016-03-02 19:40:53 +08:00
|
|
|
url += [z,x,y].join('/');
|
|
|
|
url += '.' + format;
|
|
|
|
|
2017-12-05 19:09:31 +08:00
|
|
|
const queryParams = {};
|
|
|
|
|
2016-03-02 19:40:53 +08:00
|
|
|
if (self.apiKey) {
|
2017-12-05 19:09:31 +08:00
|
|
|
queryParams.api_key = self.apiKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Object.keys(queryParams).length) {
|
|
|
|
url += '?' + qs.stringify(queryParams);
|
2016-03-02 19:40:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var request = {
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-08-01 00:23:17 +08:00
|
|
|
var expectedResponse = Object.assign({}, {
|
|
|
|
status: 200,
|
2016-03-02 19:40:53 +08:00
|
|
|
headers: {
|
2017-08-01 00:23:17 +08:00
|
|
|
'Content-Type': 'image/png'
|
2016-03-02 19:40:53 +08:00
|
|
|
}
|
2017-08-01 00:23:17 +08:00
|
|
|
}, params.response);
|
|
|
|
|
2016-03-17 19:45:05 +08:00
|
|
|
var isPng = format.match(/png$/);
|
2016-03-02 19:40:53 +08:00
|
|
|
|
|
|
|
if (isPng) {
|
|
|
|
request.encoding = 'binary';
|
|
|
|
}
|
|
|
|
|
2017-04-25 00:55:08 +08:00
|
|
|
var isMvt = format.match(/mvt$/);
|
|
|
|
|
|
|
|
if (isMvt) {
|
|
|
|
request.encoding = 'binary';
|
2017-07-18 01:43:59 +08:00
|
|
|
if (expectedResponse.status === 200) {
|
|
|
|
expectedResponse.headers['Content-Type'] = 'application/x-protobuf';
|
|
|
|
}
|
2017-04-25 00:55:08 +08:00
|
|
|
}
|
|
|
|
|
2017-08-01 00:23:17 +08:00
|
|
|
|
2017-04-28 20:46:36 +08:00
|
|
|
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';
|
|
|
|
}
|
|
|
|
|
2017-07-19 02:50:31 +08:00
|
|
|
if (params.contentType) {
|
|
|
|
expectedResponse.headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
|
|
}
|
|
|
|
|
2017-10-09 23:51:42 +08:00
|
|
|
assert.response(self.server, request, expectedResponse, resErr2errRes(this));
|
2016-03-02 19:40:53 +08:00
|
|
|
},
|
2017-10-09 23:51:42 +08:00
|
|
|
function finish(err, res) {
|
2017-10-06 20:41:50 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
2017-07-06 01:09:14 +08:00
|
|
|
}
|
2017-10-06 20:41:50 +08:00
|
|
|
|
|
|
|
var body;
|
|
|
|
switch (res.headers['content-type']) {
|
|
|
|
case 'image/png':
|
|
|
|
body = mapnik.Image.fromBytes(new Buffer(res.body, 'binary'));
|
|
|
|
break;
|
|
|
|
case 'application/x-protobuf':
|
|
|
|
body = new mapnik.VectorTile(z, x, y);
|
|
|
|
body.setDataSync(new Buffer(res.body, 'binary'));
|
|
|
|
break;
|
|
|
|
case 'application/json; charset=utf-8':
|
|
|
|
body = JSON.parse(res.body);
|
|
|
|
break;
|
|
|
|
default:
|
2017-10-06 21:24:58 +08:00
|
|
|
body = res.body;
|
2017-10-06 20:41:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(err, res, body);
|
2016-03-02 19:40:53 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2017-12-05 19:59:32 +08:00
|
|
|
TestClient.prototype.getLayergroup = function (params, callback) {
|
|
|
|
// jshint maxcomplexity: 7
|
2016-03-14 23:42:51 +08:00
|
|
|
var self = this;
|
|
|
|
|
|
|
|
if (!callback) {
|
2017-12-05 19:09:31 +08:00
|
|
|
callback = params;
|
2017-12-05 19:59:32 +08:00
|
|
|
params = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!params) {
|
|
|
|
params = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!params.response) {
|
|
|
|
params.response = {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
2016-03-14 23:42:51 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
|
|
|
|
2017-12-05 19:09:31 +08:00
|
|
|
const queryParams = {};
|
|
|
|
|
|
|
|
if (self.apiKey) {
|
|
|
|
queryParams.api_key = self.apiKey;
|
|
|
|
}
|
|
|
|
|
2017-12-13 02:23:21 +08:00
|
|
|
if (params.aggregation !== undefined) {
|
2017-12-05 19:09:31 +08:00
|
|
|
queryParams.aggregation = params.aggregation;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Object.keys(queryParams).length) {
|
|
|
|
url += '?' + qs.stringify(queryParams);
|
2016-03-14 23:42:51 +08:00
|
|
|
}
|
|
|
|
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-03-14 23:42:51 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(self.mapConfig)
|
|
|
|
},
|
2017-12-05 19:09:31 +08:00
|
|
|
params.response,
|
2016-03-14 23:42:51 +08:00
|
|
|
function(res, err) {
|
2017-10-06 21:24:58 +08:00
|
|
|
var parsedBody;
|
2017-05-26 19:06:04 +08:00
|
|
|
// If there is a response, we are still interested in catching the created keys
|
|
|
|
// to be able to delete them on the .drain() method.
|
|
|
|
if (res) {
|
2017-10-06 21:24:58 +08:00
|
|
|
parsedBody = JSON.parse(res.body);
|
2017-05-26 19:06:04 +08:00
|
|
|
if (parsedBody.layergroupid) {
|
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0;
|
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
|
|
|
}
|
|
|
|
}
|
2016-03-14 23:42:51 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
2017-08-01 00:22:13 +08:00
|
|
|
return callback(null, parsedBody);
|
2016-03-14 23:42:51 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2017-08-01 17:46:48 +08:00
|
|
|
TestClient.prototype.getStaticCenter = function (params, callback) {
|
|
|
|
var self = this;
|
|
|
|
|
2018-04-17 00:55:42 +08:00
|
|
|
let { layergroupid, zoom, lat, lng, width, height, format } = params;
|
2017-08-01 17:46:48 +08:00
|
|
|
|
|
|
|
var url = `/api/v1/map/`;
|
|
|
|
|
|
|
|
if (this.apiKey) {
|
|
|
|
url += '?' + qs.stringify({api_key: this.apiKey});
|
|
|
|
}
|
|
|
|
|
|
|
|
step(
|
|
|
|
function createLayergroup() {
|
|
|
|
var next = this;
|
|
|
|
|
|
|
|
if (layergroupid) {
|
|
|
|
return next(null, layergroupid);
|
|
|
|
}
|
|
|
|
|
2017-10-06 21:24:58 +08:00
|
|
|
var data = self.mapConfig;
|
2017-08-01 17:46:48 +08:00
|
|
|
var path = url;
|
|
|
|
|
|
|
|
assert.response(self.server,
|
|
|
|
{
|
|
|
|
url: path,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(data)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
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).layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2017-10-06 21:27:03 +08:00
|
|
|
function getStaticResult(err, layergroupId) {
|
2017-08-01 17:46:48 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
2017-10-06 21:27:03 +08:00
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
2017-10-06 20:41:50 +08:00
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
2017-08-01 17:46:48 +08:00
|
|
|
|
2018-05-23 00:27:50 +08:00
|
|
|
const layergroupid = layergroupidTemplate(layergroupId, params);
|
|
|
|
|
|
|
|
url = `/api/v1/map/static/center/${layergroupid}/${zoom}/${lat}/${lng}/${width}/${height}.${format}`;
|
2017-08-01 17:46:48 +08:00
|
|
|
|
|
|
|
if (self.apiKey) {
|
|
|
|
url += '?' + qs.stringify({api_key: self.apiKey});
|
|
|
|
}
|
|
|
|
|
|
|
|
var request = {
|
|
|
|
url: url,
|
|
|
|
encoding: 'binary',
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var expectedResponse = Object.assign({}, {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'image/png'
|
|
|
|
}
|
|
|
|
}, params.response);
|
|
|
|
|
2017-10-09 23:51:42 +08:00
|
|
|
assert.response(self.server, request, expectedResponse, resErr2errRes(this));
|
2017-08-01 17:46:48 +08:00
|
|
|
},
|
2017-10-09 23:51:42 +08:00
|
|
|
function(err, res) {
|
2017-10-06 20:41:50 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
var body;
|
|
|
|
switch (res.headers['content-type']) {
|
|
|
|
case 'image/png':
|
|
|
|
body = mapnik.Image.fromBytes(new Buffer(res.body, 'binary'));
|
|
|
|
break;
|
|
|
|
case 'application/json; charset=utf-8':
|
|
|
|
body = JSON.parse(res.body);
|
|
|
|
break;
|
|
|
|
default:
|
2017-10-06 21:24:58 +08:00
|
|
|
body = res.body;
|
2017-10-06 20:41:50 +08:00
|
|
|
break;
|
2017-08-01 17:46:48 +08:00
|
|
|
}
|
2017-10-06 20:41:50 +08:00
|
|
|
|
|
|
|
return callback(err, res, body);
|
2017-08-01 17:46:48 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2016-05-05 23:52:37 +08:00
|
|
|
TestClient.prototype.getNodeStatus = function(nodeName, callback) {
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
|
|
|
|
|
|
|
if (this.apiKey) {
|
|
|
|
url += '?' + qs.stringify({api_key: this.apiKey});
|
|
|
|
}
|
|
|
|
|
|
|
|
var nodes = {};
|
|
|
|
step(
|
|
|
|
function createLayergroup() {
|
|
|
|
var next = this;
|
2017-07-19 02:50:31 +08:00
|
|
|
assert.response(self.server,
|
2016-05-05 23:52:37 +08:00
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(self.mapConfig)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
|
|
|
|
nodes = parsedBody.metadata.analyses.reduce(function(nodes, analysis) {
|
|
|
|
return Object.keys(analysis.nodes).reduce(function(nodes, nodeName) {
|
|
|
|
var node = analysis.nodes[nodeName];
|
|
|
|
nodes[nodeName] = node.url.http;
|
|
|
|
return nodes;
|
|
|
|
}, nodes);
|
|
|
|
}, nodes);
|
|
|
|
|
|
|
|
return next(null, parsedBody.layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2017-10-06 21:27:03 +08:00
|
|
|
function getNodeStatusResult(err, layergroupId) {
|
2016-05-05 23:52:37 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
2017-10-06 20:41:50 +08:00
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
2016-05-05 23:52:37 +08:00
|
|
|
|
|
|
|
url = urlParser.parse(nodes[nodeName]).path;
|
|
|
|
|
|
|
|
if (self.apiKey) {
|
|
|
|
url += '?' + qs.stringify({api_key: self.apiKey});
|
|
|
|
}
|
|
|
|
|
|
|
|
var request = {
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var expectedResponse = {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-10-09 23:51:42 +08:00
|
|
|
assert.response(self.server, request, expectedResponse, resErr2errRes(this));
|
2016-05-05 23:52:37 +08:00
|
|
|
},
|
2017-10-09 23:51:42 +08:00
|
|
|
function finish(err, res) {
|
2017-10-06 20:41:50 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
return callback(null, res, JSON.parse(res.body));
|
2016-05-05 23:52:37 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2017-08-01 00:12:33 +08:00
|
|
|
TestClient.prototype.getAttributes = function(params, callback) {
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
if (!Number.isFinite(params.featureId)) {
|
2017-10-06 21:24:58 +08:00
|
|
|
throw new Error('featureId param must be a number');
|
2017-08-01 00:12:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!Number.isFinite(params.layer)) {
|
2017-10-06 21:24:58 +08:00
|
|
|
throw new Error('layer param must be a number');
|
2017-08-01 00:12:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var url = '/api/v1/map';
|
|
|
|
|
|
|
|
if (this.apiKey) {
|
|
|
|
url += '?' + qs.stringify({ api_key: this.apiKey });
|
|
|
|
}
|
|
|
|
|
|
|
|
var layergroupid;
|
|
|
|
|
|
|
|
if (params.layergroupid) {
|
2017-10-06 21:24:58 +08:00
|
|
|
layergroupid = params.layergroupid;
|
2017-08-01 00:12:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
step(
|
|
|
|
function createLayergroup() {
|
|
|
|
var next = this;
|
|
|
|
|
|
|
|
if (layergroupid) {
|
|
|
|
return next(null, layergroupid);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.response(self.server,
|
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(self.mapConfig)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return next(err);
|
|
|
|
}
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
|
|
|
|
return next(null, parsedBody.layergroupid);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2017-10-06 21:27:03 +08:00
|
|
|
function getAttributes(err, layergroupId) {
|
2017-08-01 00:12:33 +08:00
|
|
|
assert.ifError(err);
|
|
|
|
|
2017-10-06 21:27:03 +08:00
|
|
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
2017-10-06 20:41:50 +08:00
|
|
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
2017-08-01 00:12:33 +08:00
|
|
|
|
2017-10-06 21:27:03 +08:00
|
|
|
url = `/api/v1/map/${layergroupId}/${params.layer}/attributes/${params.featureId}`;
|
2017-08-01 00:12:33 +08:00
|
|
|
|
|
|
|
if (self.apiKey) {
|
|
|
|
url += '?' + qs.stringify({api_key: self.apiKey});
|
|
|
|
}
|
|
|
|
|
|
|
|
var request = {
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var expectedResponse = params.response || {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-10-09 23:51:42 +08:00
|
|
|
assert.response(self.server, request, expectedResponse, resErr2errRes(this));
|
2017-08-01 00:12:33 +08:00
|
|
|
},
|
2017-10-09 23:51:42 +08:00
|
|
|
function finish(err, res) {
|
2017-10-06 20:41:50 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
2017-08-01 00:12:33 +08:00
|
|
|
}
|
2017-10-06 20:41:50 +08:00
|
|
|
var attributes = JSON.parse(res.body);
|
|
|
|
return callback(null, res, attributes);
|
2017-08-01 00:12:33 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2016-02-05 19:59:33 +08:00
|
|
|
TestClient.prototype.drain = function(callback) {
|
|
|
|
helper.deleteRedisKeys(this.keysToDelete, callback);
|
|
|
|
};
|
2016-05-13 22:56:52 +08:00
|
|
|
|
|
|
|
module.exports.getStaticMap = function getStaticMap(templateName, params, callback) {
|
2017-07-19 02:50:31 +08:00
|
|
|
var self = this;
|
|
|
|
|
|
|
|
self.server = new CartodbWindshaft(serverOptions);
|
|
|
|
|
2016-05-13 22:56:52 +08:00
|
|
|
if (!callback) {
|
|
|
|
callback = params;
|
|
|
|
params = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
var url = '/api/v1/map/static/named/' + templateName + '/640/480.png';
|
|
|
|
|
|
|
|
if (params !== null) {
|
|
|
|
url += '?' + qs.stringify(params);
|
|
|
|
}
|
|
|
|
|
|
|
|
var requestOptions = {
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
},
|
|
|
|
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);
|
|
|
|
|
2017-10-06 21:27:03 +08:00
|
|
|
assert.response(server, requestOptions, expectedResponse, function (res, err) {
|
2016-05-13 22:56:52 +08:00
|
|
|
helper.deleteRedisKeys({'user:localhost:mapviews:global': 5}, function() {
|
|
|
|
return callback(err, mapnik.Image.fromBytes(new Buffer(res.body, 'binary')));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2017-07-19 02:50:31 +08:00
|
|
|
|
|
|
|
TestClient.prototype.setUserRenderTimeoutLimit = function (user, userTimeoutLimit, callback) {
|
|
|
|
const userTimeoutLimitsKey = `limits:timeout:${user}`;
|
|
|
|
const params = [
|
|
|
|
userTimeoutLimitsKey,
|
|
|
|
'render', userTimeoutLimit,
|
|
|
|
'render_public', userTimeoutLimit
|
|
|
|
];
|
|
|
|
|
|
|
|
this.keysToDelete[userTimeoutLimitsKey] = 5;
|
|
|
|
|
|
|
|
helper.configureMetadata('hmset', params, callback);
|
2017-07-26 01:15:43 +08:00
|
|
|
};
|
|
|
|
|
2018-04-12 22:32:44 +08:00
|
|
|
TestClient.prototype.getDBConnection = function () {
|
|
|
|
const dbname = _.template(global.environment.postgres_auth_user, { user_id: 1 }) + '_db';
|
|
|
|
|
|
|
|
const psql = new PSQL({
|
|
|
|
user: 'postgres',
|
|
|
|
dbname: dbname,
|
|
|
|
host: global.environment.postgres.host,
|
|
|
|
port: global.environment.postgres.port
|
|
|
|
});
|
|
|
|
|
|
|
|
return psql;
|
|
|
|
};
|
|
|
|
|
2017-08-10 23:09:05 +08:00
|
|
|
TestClient.prototype.setUserDatabaseTimeoutLimit = function (timeoutLimit, callback) {
|
2017-07-26 01:15:43 +08:00
|
|
|
const dbname = _.template(global.environment.postgres_auth_user, { user_id: 1 }) + '_db';
|
2017-10-06 21:24:58 +08:00
|
|
|
const dbuser = _.template(global.environment.postgres_auth_user, { user_id: 1 });
|
2017-07-28 19:23:13 +08:00
|
|
|
const publicuser = global.environment.postgres.user;
|
2017-07-26 01:15:43 +08:00
|
|
|
|
2018-11-06 19:17:39 +08:00
|
|
|
// IMPORTANT: node-postgres uses internallly a singleton, to refresh all pull connections
|
|
|
|
// you need to ensure that your dependency tree has only one working version of `cartodb-psql` & `node-postgres`
|
|
|
|
// if not, test using this function cannot ensure that all connections have the new settings (STATEMENT_TIMEOUT)
|
|
|
|
//
|
|
|
|
// TODO: upgrade to node-postgres@7.x
|
2018-11-06 00:16:22 +08:00
|
|
|
const psql = new PSQL({
|
|
|
|
user: 'postgres',
|
|
|
|
dbname: dbname,
|
|
|
|
host: global.environment.postgres.host,
|
|
|
|
port: global.environment.postgres.port
|
|
|
|
});
|
2017-07-26 01:15:43 +08:00
|
|
|
|
2018-11-06 00:16:22 +08:00
|
|
|
step(
|
|
|
|
function configureTimeouts () {
|
|
|
|
const timeoutSQLs = [
|
|
|
|
`ALTER ROLE "${publicuser}" SET STATEMENT_TIMEOUT TO ${timeoutLimit}`,
|
|
|
|
`ALTER ROLE "${dbuser}" SET STATEMENT_TIMEOUT TO ${timeoutLimit}`,
|
|
|
|
`ALTER DATABASE "${dbname}" SET STATEMENT_TIMEOUT TO ${timeoutLimit}`
|
|
|
|
];
|
2018-11-05 23:50:52 +08:00
|
|
|
|
2018-11-06 00:16:22 +08:00
|
|
|
const group = this.group();
|
2018-11-05 23:50:52 +08:00
|
|
|
|
2018-11-06 00:16:22 +08:00
|
|
|
timeoutSQLs.forEach(sql => psql.query(sql, group()));
|
|
|
|
},
|
|
|
|
// we need to guarantee all new connections have the new settings
|
|
|
|
function refreshPoolConnection () {
|
2018-11-06 01:14:26 +08:00
|
|
|
psql.end(() => callback());
|
2018-11-06 00:16:22 +08:00
|
|
|
}
|
|
|
|
);
|
2017-07-26 01:15:43 +08:00
|
|
|
};
|
2017-08-01 00:24:42 +08:00
|
|
|
|
2017-11-14 20:46:47 +08:00
|
|
|
TestClient.prototype.getAnalysesCatalog = function (params, callback) {
|
|
|
|
var url = '/api/v1/map/analyses/catalog';
|
2017-08-01 00:24:42 +08:00
|
|
|
|
2017-11-14 20:46:47 +08:00
|
|
|
if (this.apiKey) {
|
|
|
|
url += '?' + qs.stringify({api_key: this.apiKey});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (params.jsonp) {
|
|
|
|
url += '&' + qs.stringify({callback: params.jsonp});
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.response(this.server,
|
|
|
|
{
|
|
|
|
url: url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: params.status || 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': params.jsonp ?
|
|
|
|
'text/javascript; charset=utf-8' :
|
|
|
|
'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
var parsedBody = params.jsonp ? res.body : JSON.parse(res.body);
|
|
|
|
|
|
|
|
return callback(null, parsedBody);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
};
|
2018-03-03 01:22:53 +08:00
|
|
|
|
2018-04-06 21:26:11 +08:00
|
|
|
TestClient.prototype.getNamedMapList = function(params, callback) {
|
|
|
|
const request = {
|
|
|
|
url: `/api/v1/map/named?${qs.stringify({ api_key: this.apiKey })}`,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let expectedResponse = {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (params.response) {
|
|
|
|
expectedResponse = Object.assign(expectedResponse, params.response);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.response(this.server, request, expectedResponse, (res, err) => {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
const body = JSON.parse(res.body);
|
|
|
|
return callback(null, res, body);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-03-03 01:22:53 +08:00
|
|
|
TestClient.prototype.getNamedTile = function (name, z, x, y, format, options, callback) {
|
|
|
|
const { params } = options;
|
|
|
|
|
|
|
|
if (!this.apiKey) {
|
|
|
|
return callback(new Error('apiKey param is mandatory to create a new template'));
|
|
|
|
}
|
|
|
|
|
|
|
|
const createTemplateRequest = {
|
|
|
|
url: `/api/v1/map/named?${qs.stringify({ api_key: this.apiKey })}`,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(this.template)
|
|
|
|
};
|
|
|
|
|
|
|
|
const createTemplateResponse = {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
assert.response(this.server, createTemplateRequest, createTemplateResponse, (res, err) => {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
const templateId = JSON.parse(res.body).template_id;
|
|
|
|
const queryParams = params ? `?${qs.stringify(params)}` : '';
|
|
|
|
const url = `/api/v1/map/named/${templateId}/all/${[z,x,y].join('/')}.${format}${queryParams}`;
|
|
|
|
const namedTileRequest = {
|
|
|
|
url,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
},
|
|
|
|
encoding: 'binary'
|
|
|
|
};
|
|
|
|
|
|
|
|
let contentType;
|
|
|
|
switch (format) {
|
|
|
|
case 'png':
|
|
|
|
contentType = 'image/png';
|
|
|
|
break;
|
|
|
|
case 'mvt':
|
|
|
|
contentType = 'application/x-protobuf';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
contentType = 'application/json';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
const namedTileResponse = Object.assign({
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'content-type': contentType
|
|
|
|
}
|
|
|
|
}, options.response);
|
|
|
|
|
|
|
|
assert.response(this.server, namedTileRequest, namedTileResponse, (res, err) => {
|
|
|
|
let body;
|
|
|
|
switch (res.headers['content-type']) {
|
|
|
|
case 'image/png':
|
|
|
|
body = mapnik.Image.fromBytes(new Buffer(res.body, 'binary'));
|
|
|
|
break;
|
|
|
|
case 'application/x-protobuf':
|
|
|
|
body = new mapnik.VectorTile(z, x, y);
|
|
|
|
body.setDataSync(new Buffer(res.body, 'binary'));
|
|
|
|
break;
|
|
|
|
case 'application/json; charset=utf-8':
|
|
|
|
body = JSON.parse(res.body);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
body = res.body;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(err, res, body);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2018-04-12 18:43:41 +08:00
|
|
|
|
|
|
|
TestClient.prototype.createTemplate = function (params, callback) {
|
|
|
|
if (!this.apiKey) {
|
|
|
|
return callback(new Error('apiKey param is mandatory to create a new template'));
|
|
|
|
}
|
|
|
|
|
|
|
|
const createTemplateRequest = {
|
|
|
|
url: `/api/v1/map/named?${qs.stringify({ api_key: this.apiKey })}`,
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(this.template)
|
|
|
|
};
|
|
|
|
|
|
|
|
let createTemplateResponse = {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (params.response) {
|
|
|
|
createTemplateResponse = Object.assign(createTemplateResponse, params.response);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.response(this.server, createTemplateRequest, createTemplateResponse, (res, err) => {
|
2018-04-12 20:46:08 +08:00
|
|
|
let body;
|
|
|
|
switch (res.headers['content-type']) {
|
|
|
|
case 'application/json; charset=utf-8':
|
|
|
|
body = JSON.parse(res.body);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
body = res.body;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(err, res, body);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
TestClient.prototype.deleteTemplate = function (params, callback) {
|
|
|
|
if (!this.apiKey) {
|
|
|
|
return callback(new Error('apiKey param is mandatory to create a new template'));
|
|
|
|
}
|
|
|
|
|
|
|
|
const deleteTemplateRequest = {
|
|
|
|
url: `/api/v1/map/named/${params.templateId}?${qs.stringify({ api_key: this.apiKey })}`,
|
|
|
|
method: 'DELETE',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let deleteTemplateResponse = {
|
|
|
|
status: 204,
|
|
|
|
headers: {}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (params.response) {
|
|
|
|
deleteTemplateResponse = Object.assign(deleteTemplateResponse, params.response);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.response(this.server, deleteTemplateRequest, deleteTemplateResponse, (res, err) => {
|
|
|
|
let body;
|
|
|
|
switch (res.headers['content-type']) {
|
|
|
|
case 'application/json; charset=utf-8':
|
|
|
|
body = JSON.parse(res.body);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
body = res.body;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(err, res, body);
|
2018-04-12 18:43:41 +08:00
|
|
|
});
|
|
|
|
};
|
2018-04-12 22:03:02 +08:00
|
|
|
|
|
|
|
TestClient.prototype.updateTemplate = function (params, callback) {
|
|
|
|
if (!this.apiKey) {
|
|
|
|
return callback(new Error('apiKey param is mandatory to create a new template'));
|
|
|
|
}
|
|
|
|
|
|
|
|
const updateTemplateRequest = {
|
|
|
|
url: `/api/v1/map/named/${params.templateId}?${qs.stringify({ api_key: this.apiKey })}`,
|
|
|
|
method: 'PUT',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(params.templateData)
|
|
|
|
};
|
|
|
|
|
|
|
|
let updateTemplateResponse = {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (params.response) {
|
|
|
|
updateTemplateResponse = Object.assign(updateTemplateResponse, params.response);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.response(this.server, updateTemplateRequest, updateTemplateResponse, (res, err) => {
|
|
|
|
let body;
|
|
|
|
switch (res.headers['content-type']) {
|
|
|
|
case 'application/json; charset=utf-8':
|
|
|
|
body = JSON.parse(res.body);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
body = res.body;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-04-12 22:22:56 +08:00
|
|
|
return callback(err, res, body);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
TestClient.prototype.getTemplate = function (params, callback) {
|
|
|
|
if (!this.apiKey) {
|
|
|
|
return callback(new Error('apiKey param is mandatory to create a new template'));
|
|
|
|
}
|
|
|
|
|
|
|
|
const getTemplateRequest = {
|
|
|
|
url: `/api/v1/map/named/${params.templateId}?${qs.stringify({ api_key: this.apiKey })}`,
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let getTemplateResponse = {
|
|
|
|
status: 200,
|
|
|
|
headers: {
|
|
|
|
'Content-Type': 'application/json; charset=utf-8'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (params.response) {
|
|
|
|
getTemplateResponse = Object.assign(getTemplateResponse, params.response);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.response(this.server, getTemplateRequest, getTemplateResponse, (res, err) => {
|
|
|
|
let body;
|
|
|
|
switch (res.headers['content-type']) {
|
|
|
|
case 'application/json; charset=utf-8':
|
|
|
|
body = JSON.parse(res.body);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
body = res.body;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-04-12 22:03:02 +08:00
|
|
|
return callback(err, res, body);
|
|
|
|
});
|
2018-04-12 23:51:33 +08:00
|
|
|
};
|