Compare commits

..

24 Commits

Author SHA1 Message Date
Raul Ochoa
9f18e2d27d Release 2.42.0 2016-05-16 19:58:22 +02:00
Raul Ochoa
1ac6ead4b2 Update news 2016-05-16 19:57:51 +02:00
Raul Ochoa
8f51418d84 Merge pull request #453 from CartoDB/issue-450
Fix named maps with analysis
2016-05-13 17:13:29 +02:00
Raul Ochoa
c12e5f7a27 Fix named maps with analysis
Named map provider was missing analysis backend dependency

Fixes #450
2016-05-13 16:57:27 +02:00
Raul Ochoa
1c2354dc49 Merge pull request #452 from CartoDB/turbo-carto-split-strategy
Use split strategy for head/tails turbo-carto quantification
2016-05-13 13:20:12 +02:00
Raul Ochoa
2e26e2e126 Use split strategy for head/tails turbo-carto quantification 2016-05-13 12:57:43 +02:00
Raul Ochoa
94639f7e0c Merge pull request #451 from CartoDB/turbo-carto-errors
Improve turbo-carto related errors
2016-05-13 12:54:17 +02:00
Raul Ochoa
f3957b4fce Fix test expectations for turbo-carto errors 2016-05-13 12:42:18 +02:00
Raul Ochoa
61765d20e1 Fail on turbo-carto specific errors
This will try to fallback on postcss errors so it still targets
carto parser in those cases.

Closes #434
2016-05-13 12:10:05 +02:00
Raul Ochoa
503636f9fb Upgrade to turbo-carto 0.9.0 2016-05-13 12:09:11 +02:00
Raul Ochoa
4abadec9c4 Use the more suitable getLayergroup to validate regression 2016-05-13 00:49:09 +02:00
Raul Ochoa
7c2924ae14 Merge pull request #448 from CartoDB/upgrade-turbo-carto
Upgrades turbo-carto to 0.8.0
2016-05-11 20:09:41 +02:00
Raul Ochoa
bfdaf67a9b Upgrades turbo-carto to 0.8.0 2016-05-11 19:57:05 +02:00
Raul Ochoa
e0ade85565 Stubs next version 2016-05-11 18:53:17 +02:00
Raul Ochoa
c5afc0dc94 Release 2.41.1 2016-05-11 18:51:05 +02:00
Raul Ochoa
a7e00c5856 Merge pull request #447 from CartoDB/upgrade-camshaft
Upgrades camshaft to 0.8.0
2016-05-11 18:50:14 +02:00
Raul Ochoa
2482accb42 Upgrades camshaft to 0.8.0 2016-05-11 18:39:07 +02:00
Raul Ochoa
3e4f71d873 Nicer error message when missing sql from layer options
Fixes #446
2016-05-11 18:24:47 +02:00
Raul Ochoa
bbadd46766 Stubs next version 2016-05-11 16:47:33 +02:00
Raul Ochoa
b1f618a98e Release 2.41.0 2016-05-11 16:46:57 +02:00
Raul Ochoa
cdf3fe3a25 Bumps version 2016-05-11 16:45:36 +02:00
Raul Ochoa
1440841ac8 Merge pull request #445 from CartoDB/upgrade-camshaft
Upgrade camshaft to 0.7.0
2016-05-11 16:44:07 +02:00
Raul Ochoa
fc57fd2638 Upgrade camshaft to 0.7.0 2016-05-11 16:25:42 +02:00
Raul Ochoa
776cb8d47a Stubs next version 2016-05-10 17:26:27 +02:00
15 changed files with 487 additions and 257 deletions

33
NEWS.md
View File

@@ -1,5 +1,38 @@
# Changelog
## 2.42.0
Released 2016-05-16
Bug fixes:
- Fix named maps with analysis #453
Enhancements:
- Use split strategy for head/tails turbo-carto quantification
Announcements:
- Upgrades turbo-carto to [0.9.0](https://github.com/CartoDB/turbo-carto/releases/tag/0.9.0)
## 2.41.1
Released 2016-05-11
Announcements:
- Upgrades camshaft to [0.8.0](https://github.com/CartoDB/camshaft/releases/tag/0.8.0)
Bug fixes:
- Nicer error message when missing sql from layer options #446
## 2.41.0
Released 2016-05-11
Announcements:
- Upgrades camshaft to [0.7.0](https://github.com/CartoDB/camshaft/releases/tag/0.7.0)
## 2.40.0
Released 2016-05-10

View File

@@ -13,7 +13,7 @@ var affectedTableRegexCache = {
};
function prepareSql(sql) {
return sql
return sql && sql
.replace(affectedTableRegexCache.bbox, 'ST_MakeEnvelope(0,0,0,0)')
.replace(affectedTableRegexCache.scale_denominator, '0')
.replace(affectedTableRegexCache.pixel_width, '1')

View File

@@ -8,15 +8,15 @@ var queue = require('queue-async');
var LruCache = require("lru-cache");
function NamedMapProviderCache(templateMaps, pgConnection, metadataBackend, userLimitsApi, overviewsAdapter,
turboCartoAdapter) {
function NamedMapProviderCache(templateMaps, pgConnection, metadataBackend, analysisBackend, userLimitsApi,
overviewsAdapter, turboCartoAdapter) {
this.templateMaps = templateMaps;
this.pgConnection = pgConnection;
this.metadataBackend = metadataBackend;
this.userLimitsApi = userLimitsApi;
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps);
this.analysisMapConfigAdapter = new AnalysisMapConfigAdapter();
this.analysisMapConfigAdapter = new AnalysisMapConfigAdapter(analysisBackend);
this.overviewsAdapter = overviewsAdapter;
this.turboCartoAdapter = turboCartoAdapter;

View File

@@ -157,6 +157,7 @@ module.exports = function(serverOptions) {
templateMaps,
pgConnection,
metadataBackend,
analysisBackend,
userLimitsApi,
overviewsAdapter,
turboCartoAdapter

View File

@@ -23,6 +23,10 @@ var methodTemplates = Object.keys(methods).reduce(function(methodTemplates, meth
return methodTemplates;
}, {});
var method2strategy = {
headtails: 'split'
};
function PostgresDatasource (pgQueryRunner, username, query) {
this.pgQueryRunner = pgQueryRunner;
this.username = username;
@@ -48,7 +52,7 @@ PostgresDatasource.prototype.getRamp = function (column, buckets, method, callba
return a - b;
});
return callback(null, ramp);
return callback(null, { ramp: ramp, strategy: method2strategy[methodName] });
});
};

View File

@@ -38,12 +38,18 @@ TurboCartoAdapter.prototype._parseCartoCss = function (username, layer, callback
}
this.turboCartoParser.process(username, layer.options.cartocss, layer.options.sql, function (err, cartocss) {
// Ignore turbo-carto errors and continue
if (!err && cartocss) {
layer.options.cartocss = cartocss;
// Only return turbo-carto errors
if (err && err.name === 'TurboCartoError') {
err = new Error('turbo-carto: ' + err.message);
err.http_status = 400;
return callback(err);
}
callback(null, layer);
// Try to continue in the rest of the cases
if (cartocss) {
layer.options.cartocss = cartocss;
}
return callback(null, layer);
});
};

59
npm-shrinkwrap.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "windshaft-cartodb",
"version": "2.40.0",
"version": "2.42.0",
"dependencies": {
"body-parser": {
"version": "1.14.2",
@@ -13,9 +13,9 @@
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz"
},
"content-type": {
"version": "1.0.1",
"version": "1.0.2",
"from": "content-type@>=1.0.1 <1.1.0",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz"
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz"
},
"depd": {
"version": "1.1.0",
@@ -34,7 +34,7 @@
},
"statuses": {
"version": "1.2.1",
"from": "statuses@>=1.2.1 <1.3.0",
"from": "statuses@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz"
}
}
@@ -80,7 +80,7 @@
},
"type-is": {
"version": "1.6.12",
"from": "type-is@>=1.6.6 <1.7.0",
"from": "type-is@>=1.6.10 <1.7.0",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.12.tgz",
"dependencies": {
"media-typer": {
@@ -90,7 +90,7 @@
},
"mime-types": {
"version": "2.1.11",
"from": "mime-types@>=2.1.10 <2.2.0",
"from": "mime-types@>=2.1.2 <2.2.0",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
"dependencies": {
"mime-db": {
@@ -105,9 +105,9 @@
}
},
"camshaft": {
"version": "0.6.0",
"from": "camshaft@0.6.0",
"resolved": "https://registry.npmjs.org/camshaft/-/camshaft-0.6.0.tgz",
"version": "0.8.0",
"from": "camshaft@0.8.0",
"resolved": "https://registry.npmjs.org/camshaft/-/camshaft-0.8.0.tgz",
"dependencies": {
"async": {
"version": "1.5.2",
@@ -125,28 +125,9 @@
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz"
},
"aws4": {
"version": "1.3.2",
"version": "1.4.1",
"from": "aws4@>=1.2.1 <2.0.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.3.2.tgz",
"dependencies": {
"lru-cache": {
"version": "4.0.1",
"from": "lru-cache@>=4.0.0 <5.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz",
"dependencies": {
"pseudomap": {
"version": "1.0.2",
"from": "pseudomap@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz"
},
"yallist": {
"version": "2.0.0",
"from": "yallist@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz"
}
}
}
}
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz"
},
"bl": {
"version": "1.1.2",
@@ -603,7 +584,7 @@
"dependencies": {
"mime-types": {
"version": "2.1.11",
"from": "mime-types@>=2.1.6 <2.2.0",
"from": "mime-types@>=2.1.10 <2.2.0",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
"dependencies": {
"mime-db": {
@@ -631,9 +612,9 @@
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz"
},
"content-type": {
"version": "1.0.1",
"version": "1.0.2",
"from": "content-type@>=1.0.1 <1.1.0",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz"
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz"
},
"cookie": {
"version": "0.1.5",
@@ -667,7 +648,7 @@
"dependencies": {
"unpipe": {
"version": "1.0.0",
"from": "unpipe@1.0.0",
"from": "unpipe@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz"
}
}
@@ -792,7 +773,7 @@
},
"mime-types": {
"version": "2.1.11",
"from": "mime-types@>=2.1.6 <2.2.0",
"from": "mime-types@>=2.1.10 <2.2.0",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
"dependencies": {
"mime-db": {
@@ -995,7 +976,7 @@
"dependencies": {
"async": {
"version": "1.5.2",
"from": "async@>=1.0.0 <2.0.0",
"from": "async@>=1.5.2 <2.0.0",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz"
}
}
@@ -1234,9 +1215,9 @@
"from": "step-profiler@>=0.3.0 <0.4.0"
},
"turbo-carto": {
"version": "0.7.1",
"from": "turbo-carto@0.7.1",
"resolved": "https://registry.npmjs.org/turbo-carto/-/turbo-carto-0.7.1.tgz",
"version": "0.9.0",
"from": "turbo-carto@0.9.0",
"resolved": "https://registry.npmjs.org/turbo-carto/-/turbo-carto-0.9.0.tgz",
"dependencies": {
"colorbrewer": {
"version": "1.0.0",

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "windshaft-cartodb",
"version": "2.40.0",
"version": "2.42.0",
"description": "A map tile server for CartoDB",
"keywords": [
"cartodb"
@@ -20,7 +20,7 @@
],
"dependencies": {
"body-parser": "~1.14.0",
"camshaft": "0.6.0",
"camshaft": "0.8.0",
"cartodb-psql": "~0.6.1",
"cartodb-query-tables": "~0.1.0",
"cartodb-redis": "~0.13.0",
@@ -37,7 +37,7 @@
"request": "~2.62.0",
"step": "~0.0.6",
"step-profiler": "~0.3.0",
"turbo-carto": "0.7.1",
"turbo-carto": "0.9.0",
"underscore": "~1.6.0",
"windshaft": "1.19.0"
},

View File

@@ -1,11 +1,11 @@
var assert = require('../../support/assert');
var step = require('step');
var helper = require('../../support/test_helper');
var CartodbWindshaft = require('../../../lib/cartodb/server');
var serverOptions = require('../../../lib/cartodb/server_options');
var server = new CartodbWindshaft(serverOptions);
var TestClient = require('../../support/test-client');
var LayergroupToken = require('../../../lib/cartodb/models/layergroup_token');
@@ -16,230 +16,259 @@ describe('named-maps analysis', function() {
var username = 'localhost';
var widgetsTemplateName = 'widgets-template';
var layergroupid;
var layergroup;
var keysToDelete;
beforeEach(function(done) {
keysToDelete = {};
var widgetsTemplate = {
version: '0.0.1',
name: widgetsTemplateName,
layergroup: {
version: '1.5.0',
layers: [
{
"type": "cartodb",
"options": {
"source": {
"id": "HEAD"
},
"cartocss": '#buffer { polygon-fill: red; }',
"cartocss_version": "2.3.0"
}
}
],
dataviews: {
pop_max_histogram: {
source: {
id: 'HEAD'
var widgetsTemplate = {
version: '0.0.1',
name: widgetsTemplateName,
layergroup: {
version: '1.5.0',
layers: [
{
"type": "cartodb",
"options": {
"source": {
"id": "HEAD"
},
type: 'histogram',
options: {
column: 'pop_max'
}
"cartocss": '#buffer { polygon-fill: red; }',
"cartocss_version": "2.3.0"
}
},
analyses: [
{
"id": "HEAD",
"type": "buffer",
"params": {
"source": {
"id": "2570e105-7b37-40d2-bdf4-1af889598745",
"type": "source",
"params": {
"query": "select * from populated_places_simple_reduced"
}
},
"radius": 50000
}
}
],
dataviews: {
pop_max_histogram: {
source: {
id: 'HEAD'
},
type: 'histogram',
options: {
column: 'pop_max'
}
]
}
};
var template_params = {};
step(
function createTemplate()
{
var next = this;
assert.response(
server,
{
url: '/api/v1/map/named?api_key=1234',
method: 'POST',
headers: {
host: username,
'Content-Type': 'application/json'
}
},
analyses: [
{
"id": "HEAD",
"type": "buffer",
"params": {
"source": {
"id": "2570e105-7b37-40d2-bdf4-1af889598745",
"type": "source",
"params": {
"query": "select * from populated_places_simple_reduced"
}
},
data: JSON.stringify(widgetsTemplate)
},
{
status: 200
},
function(res, err) {
next(err, res);
"radius": 50000
}
);
},
function instantiateTemplate(err, res) {
assert.ifError(err);
}
]
}
};
assert.deepEqual(JSON.parse(res.body), { template_id: widgetsTemplateName });
var next = this;
assert.response(
server,
{
url: '/api/v1/map/named/' + widgetsTemplateName,
method: 'POST',
headers: {
host: username,
'Content-Type': 'application/json'
},
data: JSON.stringify(template_params)
},
{
status: 200
},
function(res) {
next(null, res);
}
);
},
function finish(err, res) {
assert.ifError(err);
layergroup = JSON.parse(res.body);
assert.ok(layergroup.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from: " + res.body);
layergroupid = layergroup.layergroupid;
assert.ok(
Array.isArray(layergroup.metadata.analyses),
'Missing "analyses" array metadata from: ' + res.body
);
var analyses = layergroup.metadata.analyses;
assert.equal(analyses.length, 1, 'Invalid number of analyses in metadata');
var nodes = analyses[0].nodes;
var nodesIds = Object.keys(nodes);
assert.deepEqual(nodesIds, ['2570e105-7b37-40d2-bdf4-1af889598745', 'HEAD']);
nodesIds.forEach(function(nodeId) {
var node = nodes[nodeId];
assert.ok(node.hasOwnProperty('url'), 'Missing "url" attribute in node');
assert.ok(node.hasOwnProperty('status'), 'Missing "status" attribute in node');
assert.ok(!node.hasOwnProperty('query'), 'Unexpected "query" attribute in node');
});
keysToDelete['map_cfg|' + LayergroupToken.parse(layergroup.layergroupid).token] = 0;
keysToDelete['user:localhost:mapviews:global'] = 5;
return done();
}
);
});
afterEach(function(done) {
step(
function deleteTemplate(err) {
assert.ifError(err);
var next = this;
assert.response(
server,
{
url: '/api/v1/map/named/' + widgetsTemplateName + '?api_key=1234',
method: 'DELETE',
headers: {
host: username
}
},
{
status: 204
},
function(res, err) {
next(err, res);
}
);
},
function deleteRedisKeys(err) {
assert.ifError(err);
helper.deleteRedisKeys(keysToDelete, done);
}
);
});
it('should be able to retrieve images from analysis', function(done) {
beforeEach(function createTemplate(done) {
assert.response(
server,
{
url: '/api/v1/map/' + layergroupid + '/6/31/24.png',
method: 'GET',
encoding: 'binary',
url: '/api/v1/map/named?api_key=1234',
method: 'POST',
headers: {
host: username,
'Content-Type': 'application/json'
},
data: JSON.stringify(widgetsTemplate)
},
{
status: 200
},
function(res, err) {
assert.deepEqual(JSON.parse(res.body), { template_id: widgetsTemplateName });
return done(err);
}
);
});
afterEach(function deleteTemplate(done) {
assert.response(
server,
{
url: '/api/v1/map/named/' + widgetsTemplateName + '?api_key=1234',
method: 'DELETE',
headers: {
host: username
}
},
{
status: 200,
headers: {
'Content-Type': 'image/png'
}
status: 204
},
function(res, err) {
if (err) {
return done(err);
}
return done(err);
}
);
});
var fixturePath = './test/fixtures/analysis/named-map-buffer.png';
assert.imageBufferIsSimilarToFile(res.body, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) {
describe('layergroup', function() {
var layergroupid;
var layergroup;
var keysToDelete;
beforeEach(function(done) {
keysToDelete = {};
assert.response(
server,
{
url: '/api/v1/map/named/' + widgetsTemplateName,
method: 'POST',
headers: {
host: username,
'Content-Type': 'application/json'
},
data: JSON.stringify({})
},
{
status: 200
},
function(res, err) {
assert.ifError(err);
layergroup = JSON.parse(res.body);
assert.ok(layergroup.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from: " + res.body);
layergroupid = layergroup.layergroupid;
assert.ok(
Array.isArray(layergroup.metadata.analyses),
'Missing "analyses" array metadata from: ' + res.body
);
var analyses = layergroup.metadata.analyses;
assert.equal(analyses.length, 1, 'Invalid number of analyses in metadata');
var nodes = analyses[0].nodes;
var nodesIds = Object.keys(nodes);
assert.deepEqual(nodesIds, ['2570e105-7b37-40d2-bdf4-1af889598745', 'HEAD']);
nodesIds.forEach(function(nodeId) {
var node = nodes[nodeId];
assert.ok(node.hasOwnProperty('url'), 'Missing "url" attribute in node');
assert.ok(node.hasOwnProperty('status'), 'Missing "status" attribute in node');
assert.ok(!node.hasOwnProperty('query'), 'Unexpected "query" attribute in node');
});
keysToDelete['map_cfg|' + LayergroupToken.parse(layergroup.layergroupid).token] = 0;
keysToDelete['user:localhost:mapviews:global'] = 5;
return done();
}
);
});
afterEach(function(done) {
helper.deleteRedisKeys(keysToDelete, done);
});
it('should be able to retrieve images from analysis', function(done) {
assert.response(
server,
{
url: '/api/v1/map/' + layergroupid + '/6/31/24.png',
method: 'GET',
encoding: 'binary',
headers: {
host: username
}
},
{
status: 200,
headers: {
'Content-Type': 'image/png'
}
},
function(res, err) {
if (err) {
return done(err);
}
var fixturePath = './test/fixtures/analysis/named-map-buffer.png';
assert.imageBufferIsSimilarToFile(res.body, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) {
assert.ok(!err, err);
done();
});
}
);
});
it('should be able to retrieve dataviews from analysis', function(done) {
assert.response(
server,
{
url: '/api/v1/map/' + layergroupid + '/dataview/pop_max_histogram',
method: 'GET',
headers: {
host: username
}
},
{
status: 200,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
},
function(res, err) {
if (err) {
return done(err);
}
var dataview = JSON.parse(res.body);
assert.equal(dataview.type, 'histogram');
assert.equal(dataview.bins_start, 0);
done();
}
);
});
it('should be able to retrieve static map preview via layergroup', function(done) {
assert.response(
server,
{
url: '/api/v1/map/static/center/' + layergroupid + '/4/42/-3/320/240.png',
method: 'GET',
encoding: 'binary',
headers: {
host: username
}
},
{
status: 200,
headers: {
'Content-Type': 'image/png'
}
},
function(res, err) {
if (err) {
return done(err);
}
var fixturePath = './test/fixtures/analysis/named-map-buffer-layergroup-static-preview.png';
assert.imageBufferIsSimilarToFile(res.body, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) {
assert.ok(!err, err);
done();
});
}
);
});
});
describe('auto-instantiation', function() {
it('should be able to retrieve static map preview via fixed url', function(done) {
TestClient.getStaticMap(widgetsTemplateName, function(err, image) {
assert.ok(!err, err);
var fixturePath = './test/fixtures/analysis/named-map-buffer-static-preview.png';
assert.imageIsSimilarToFile(image, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) {
assert.ok(!err, err);
done();
});
}
);
});
it('should be able to retrieve dataviews from analysis', function(done) {
assert.response(
server,
{
url: '/api/v1/map/' + layergroupid + '/dataview/pop_max_histogram',
method: 'GET',
headers: {
host: username
}
},
{
status: 200,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
},
function(res, err) {
if (err) {
return done(err);
}
var dataview = JSON.parse(res.body);
assert.equal(dataview.type, 'histogram');
assert.equal(dataview.bins_start, 0);
done();
}
);
});
});
});
});

View File

@@ -0,0 +1,40 @@
require('../support/test_helper');
var assert = require('../support/assert');
var TestClient = require('../support/test-client');
describe('regressions', function() {
var ERROR_RESPONSE = {
status: 400,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
};
it('should expose a nice error when missing sql option', function(done) {
var mapConfig = {
version: '1.5.0',
layers: [
{
"type": "cartodb",
"options": {
"cartocss": '#polygons { polygon-fill: red; }',
"cartocss_version": "2.3.0"
}
}
]
};
var testClient = new TestClient(mapConfig, 1234);
testClient.getLayergroup(ERROR_RESPONSE, function(err, layergroupResult) {
assert.ok(!err, err);
assert.equal(layergroupResult.errors.length, 1);
assert.equal(layergroupResult.errors[0], 'Missing sql for layer 0 options');
testClient.drain(done);
});
});
});

View File

@@ -0,0 +1,94 @@
require('../../support/test_helper');
var assert = require('../../support/assert');
var TestClient = require('../../support/test-client');
function makeMapconfig(markerWidth, markerFill) {
return {
"version": "1.4.0",
"layers": [
{
"type": 'mapnik',
"options": {
"cartocss_version": '2.3.0',
"sql": 'SELECT * FROM populated_places_simple_reduced',
"cartocss": createCartocss(markerWidth, markerFill)
}
}
]
};
}
function createCartocss(markerWidth, markerFill) {
return [
"#populated_places_simple_reduced {",
" marker-fill-opacity: 0.9;",
" marker-line-color: #FFF;",
" marker-line-width: 1;",
" marker-line-opacity: 1;",
" marker-placement: point;",
" marker-type: ellipse;",
" marker-allow-overlap: true;",
" marker-width: " + (markerWidth || '10') + ";",
" marker-fill: " + (markerFill || 'red') + ";",
"}"
].join('\n');
}
var ERROR_RESPONSE = {
status: 400,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
};
describe('turbo-carto error cases', function() {
afterEach(function (done) {
if (this.testClient) {
this.testClient.drain(done);
}
});
it('should return invalid number of ramp error', function(done) {
this.testClient = new TestClient(makeMapconfig('ramp([pop_max], (8,24,96), (8,24,96,128))'));
this.testClient.getLayergroup(ERROR_RESPONSE, function(err, layergroup) {
assert.ok(!err, err);
assert.ok(layergroup.hasOwnProperty('errors'));
assert.equal(layergroup.errors.length, 1);
assert.ok(layergroup.errors[0].match(/^turbo-carto/));
assert.ok(layergroup.errors[0].match(/invalid\sramp\slength/i));
done();
});
});
it('should return invalid column from datasource', function(done) {
this.testClient = new TestClient(makeMapconfig(null, 'ramp([wadus_column], (red, green, blue))'));
this.testClient.getLayergroup(ERROR_RESPONSE, function(err, layergroup) {
assert.ok(!err, err);
assert.ok(layergroup.hasOwnProperty('errors'));
assert.equal(layergroup.errors.length, 1);
assert.ok(layergroup.errors[0].match(/^turbo-carto/));
assert.ok(layergroup.errors[0].match(/unable\sto\scompute\sramp/i));
assert.ok(layergroup.errors[0].match(/wadus_column/));
done();
});
});
it('should fail by falling back to normal carto parser', function(done) {
this.testClient = new TestClient(makeMapconfig('ramp([price], (8,24,96), (8,24,96));//(red, green, blue))'));
this.testClient.getLayergroup(ERROR_RESPONSE, function(err, layergroup) {
assert.ok(!err, err);
assert.ok(layergroup.hasOwnProperty('errors'));
assert.equal(layergroup.errors.length, 1);
assert.ok(!layergroup.errors[0].match(/^turbo-carto/));
assert.ok(layergroup.errors[0].match(/invalid\scode/i));
done();
});
});
});

View File

@@ -67,8 +67,12 @@ describe('turbo-carto regressions', function() {
});
it('should accept // comments', function(done) {
this.testClient.getTile(0, 0, 0, function(err) {
this.testClient.getLayergroup(function(err, layergroup) {
assert.ok(!err, err);
assert.ok(layergroup.hasOwnProperty('layergroupid'));
assert.ok(!layergroup.hasOwnProperty('errors'));
done();
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -471,3 +471,41 @@ TestClient.prototype.getNodeStatus = function(nodeName, callback) {
TestClient.prototype.drain = function(callback) {
helper.deleteRedisKeys(this.keysToDelete, callback);
};
module.exports.getStaticMap = function getStaticMap(templateName, params, callback) {
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);
assert.response(server, requestOptions, expectedResponse, function (res, err) {
helper.deleteRedisKeys({'user:localhost:mapviews:global': 5}, function() {
return callback(err, mapnik.Image.fromBytes(new Buffer(res.body, 'binary')));
});
});
};