Windshaft-cartodb/test/acceptance/ported/multilayer-error-cases-test.js

472 lines
18 KiB
JavaScript
Raw Normal View History

'use strict';
require('../../support/test-helper');
2015-07-08 05:46:58 +08:00
var assert = require('../../support/assert');
var step = require('step');
2019-10-07 15:40:50 +08:00
var cartodbServer = require('../../../lib/server');
var ServerOptions = require('./support/ported-server-options');
var testClient = require('./support/test-client');
var TestClient = require('../../support/test-client');
2015-07-08 05:46:58 +08:00
2019-10-22 01:07:24 +08:00
describe('multilayer error cases', function () {
var server;
2015-07-08 05:46:58 +08:00
before(function () {
server = cartodbServer(ServerOptions);
server.setMaxListeners(0);
});
2015-07-08 05:46:58 +08:00
// var client = null;
2019-10-22 01:07:24 +08:00
afterEach(function (done) {
if (this.client) {
return this.client.drain(done);
}
return done();
});
2019-10-22 01:07:24 +08:00
it('post layergroup with wrong Content-Type', function (done) {
2015-07-08 05:46:58 +08:00
assert.response(server, {
2019-10-02 01:34:03 +08:00
url: '/api/v1/map',
2015-07-08 05:46:58 +08:00
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/x-www-form-urlencoded'
}
2019-10-22 01:07:24 +08:00
}, {}, function (res) {
assert.strictEqual(res.statusCode, 400, res.body);
2015-07-08 05:46:58 +08:00
var parsedBody = JSON.parse(res.body);
assert.deepStrictEqual(parsedBody.errors, ['POST data must be of type application/json']);
2015-07-08 05:46:58 +08:00
done();
});
});
2019-10-22 01:07:24 +08:00
it('post layergroup with no layers', function (done) {
2015-07-08 05:46:58 +08:00
assert.response(server, {
2019-10-02 01:34:03 +08:00
url: '/api/v1/map',
2015-07-08 05:46:58 +08:00
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
}
2019-10-22 01:07:24 +08:00
}, {}, function (res) {
assert.strictEqual(res.statusCode, 400, res.body);
2015-07-08 05:46:58 +08:00
var parsedBody = JSON.parse(res.body);
assert.deepStrictEqual(parsedBody.errors, ['Missing layers array from layergroup config']);
2015-07-08 05:46:58 +08:00
done();
});
});
2019-10-22 01:07:24 +08:00
it('post layergroup jsonp errors are returned with 200 status', function (done) {
2015-07-08 05:46:58 +08:00
assert.response(server, {
2019-10-02 01:34:03 +08:00
url: '/api/v1/map?callback=test',
2015-07-08 05:46:58 +08:00
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
}
2019-10-22 01:07:24 +08:00
}, {}, function (res) {
assert.strictEqual(res.statusCode, 200);
assert.strictEqual(
2015-09-17 08:06:32 +08:00
res.body,
'/**/ typeof test === \'function\' && ' +
'test({"errors":["Missing layers array from layergroup config"],' +
2017-12-14 02:46:35 +08:00
'"errors_with_context":[{"type":"unknown",' +
'"message":"Missing layers array from layergroup config"}]});'
2015-09-17 08:06:32 +08:00
);
2015-07-08 05:46:58 +08:00
done();
});
});
2019-10-22 01:07:24 +08:00
it('layergroup with no cartocss_version', function (done) {
var layergroup = {
version: '1.0.0',
layers: [
2019-10-22 01:07:24 +08:00
{
options: {
sql: 'select cartodb_id, ST_Translate(the_geom, 50, 0) as the_geom from test_table limit 2',
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
geom_column: 'the_geom'
}
}
]
};
assert.response(server, {
2019-10-02 01:34:03 +08:00
url: '/api/v1/map',
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
},
data: JSON.stringify(layergroup)
2019-10-22 01:07:24 +08:00
}, {}, function (res) {
assert.strictEqual(res.statusCode, 400, res.body);
var parsedBody = JSON.parse(res.body);
assert.deepStrictEqual(parsedBody.errors, ['Missing cartocss_version for layer 0 options']);
done();
});
2015-07-08 05:46:58 +08:00
});
2019-10-22 01:07:24 +08:00
it('sql/cartocss combination errors', function (done) {
var layergroup = {
version: '1.0.1',
layers: [{
options: {
sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
cartocss_version: '2.0.2',
cartocss: '#layer [missing=1] { line-width:16; }',
geom_column: 'the_geom'
}
}]
};
assert.response(server, {
url: '/api/v1/map',
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
},
data: JSON.stringify(layergroup)
}, {}, function (res) {
try {
assert.strictEqual(res.statusCode, 400, res.statusCode + ': ' + res.body);
2019-10-22 01:07:24 +08:00
// See http://github.com/CartoDB/Windshaft/issues/159
var parsed = JSON.parse(res.body);
assert.ok(parsed);
assert.strictEqual(parsed.errors.length, 1);
2019-10-22 01:07:24 +08:00
var error = parsed.errors[0];
assert.ok(error.match(/column "missing" does not exist/m), error);
// cannot check for error starting with style0 until a new enough mapnik
// is used: https://github.com/mapnik/mapnik/issues/1924
// assert.ok(error.match(/^style0/), "Error doesn't start with style0: " + error);
// TODO: check which layer introduced the problem ?
done();
} catch (err) { done(err); }
});
2015-07-08 05:46:58 +08:00
});
2019-10-22 01:07:24 +08:00
it('sql/interactivity combination error', function (done) {
var layergroup = {
version: '1.0.1',
layers: [
{
options: {
sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
cartocss_version: '2.0.2',
cartocss: '#layer { line-width:16; }',
interactivity: 'i',
geom_column: 'the_geom'
}
},
{
options: {
sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
cartocss_version: '2.0.2',
cartocss: '#layer { line-width:16; }',
geom_column: 'the_geom'
}
},
{
options: {
sql: "select 1 as i, st_setsrid('LINESTRING(0 0, 1 0)'::geometry, 4326) as the_geom",
cartocss_version: '2.0.2',
cartocss: '#layer { line-width:16; }',
interactivity: 'missing',
geom_column: 'the_geom'
}
}
]
};
this.client = new TestClient(layergroup);
this.client.getLayergroup({ response: { status: 400 } }, function (err, parsed) {
assert.ok(!err, err);
assert.ok(parsed);
assert.strictEqual(parsed.errors.length, 1);
2019-10-22 01:07:24 +08:00
var error = parsed.errors[0];
assert.ok(error.match(/column "missing" does not exist/m), error);
done();
});
2015-07-08 05:46:58 +08:00
});
2019-10-22 01:07:24 +08:00
it('blank CartoCSS error', function (done) {
var layergroup = {
version: '1.0.1',
layers: [
{
options: {
sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
cartocss_version: '2.0.2',
cartocss: '#style { line-width:16 }',
interactivity: 'i',
geom_column: 'the_geom'
}
},
{
options: {
sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
cartocss_version: '2.0.2',
cartocss: '',
interactivity: 'i',
geom_column: 'the_geom'
}
}
]
};
assert.response(server, {
url: '/api/v1/map',
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
},
data: JSON.stringify(layergroup)
}, {}, function (res) {
try {
assert.strictEqual(res.statusCode, 400, res.statusCode + ': ' + res.body);
2019-10-22 01:07:24 +08:00
var parsed = JSON.parse(res.body);
assert.ok(parsed);
assert.strictEqual(parsed.errors.length, 1);
2019-10-22 01:07:24 +08:00
var error = parsed.errors[0];
assert.ok(error.match(/^style1: CartoCSS is empty/), error);
done();
} catch (err) { done(err); }
});
2015-07-08 05:46:58 +08:00
});
2019-10-22 01:07:24 +08:00
it('Invalid mapnik-geometry-type CartoCSS error', function (done) {
var layergroup = {
version: '1.0.1',
layers: [
{
options: {
sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
cartocss_version: '2.0.2',
cartocss: '#style [mapnik-geometry-type=bogus] { line-width:16 }',
geom_column: 'the_geom'
}
},
{
options: {
sql: "select 1 as i, 'LINESTRING(0 0, 1 0)'::geometry as the_geom",
cartocss_version: '2.0.2',
cartocss: '#style [mapnik-geometry-type=bogus] { line-width:16 }',
geom_column: 'the_geom'
}
}
]
};
assert.response(server, {
url: '/api/v1/map',
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
},
data: JSON.stringify(layergroup)
}, {}, function (res) {
try {
assert.strictEqual(res.statusCode, 400, res.statusCode + ': ' + res.body);
2019-10-22 01:07:24 +08:00
var parsed = JSON.parse(res.body);
assert.ok(parsed);
assert.strictEqual(parsed.errors.length, 1);
2019-10-22 01:07:24 +08:00
var error = parsed.errors[0];
// carto-0.9.3 used to say "Failed to parse expression",
// carto-0.9.5 says "not a valid keyword"
assert.ok(error.match(/^style0:.*(Failed|not a valid)/), error);
// TODO: check which layer introduced the problem ?
done();
} catch (err) { done(err); }
});
2015-07-08 05:46:58 +08:00
});
2019-10-22 01:07:24 +08:00
it("post'ing style with non existent column in filter returns 400 with error", function (done) {
var layergroup = {
2015-07-08 05:46:58 +08:00
version: '1.0.1',
layers: [
2019-10-22 01:07:24 +08:00
{
options: {
sql: 'select * from test_table limit 1',
cartocss: '#test_table::outline[address="one"], [address="two"] { marker-fill: red; }',
cartocss_version: '2.0.2',
interactivity: ['cartodb_id'],
geom_column: 'the_geom'
}
},
{
options: {
sql: 'select * from test_big_poly limit 1',
cartocss: '#test_big_poly { marker-fill:blue }',
cartocss_version: '2.0.2',
interactivity: ['cartodb_id'],
geom_column: 'the_geom'
}
}
2015-07-08 05:46:58 +08:00
]
};
assert.response(server, {
2019-10-02 01:34:03 +08:00
url: '/api/v1/map',
2015-07-08 05:46:58 +08:00
method: 'POST',
headers: {
host: 'localhost',
'Content-Type': 'application/json'
},
2015-07-08 05:46:58 +08:00
data: JSON.stringify(layergroup)
2019-10-22 01:07:24 +08:00
}, {}, function (res) {
assert.strictEqual(res.statusCode, 400, res.body);
2015-07-08 05:46:58 +08:00
var parsed = JSON.parse(res.body);
assert.strictEqual(parsed.errors.length, 1);
2015-07-08 05:46:58 +08:00
var error = parsed.errors[0];
2016-11-05 18:43:39 +08:00
assert.ok(error.match(/column "address" does not exist/m), error);
2015-07-08 05:46:58 +08:00
done();
});
});
// See https://github.com/Vizzuality/Windshaft/issues/31
2019-10-22 01:07:24 +08:00
it('bogus sql raises 400 status code', function (done) {
2015-07-08 05:46:58 +08:00
var bogusSqlMapConfig = testClient.singleLayerMapConfig('BOGUS FROM test_table');
2019-10-22 01:07:24 +08:00
testClient.createLayergroup(bogusSqlMapConfig, { statusCode: 400 }, function (err, res) {
2019-10-25 00:38:37 +08:00
assert.ifError(err);
2019-10-22 01:07:24 +08:00
assert.ok(/syntax error/.test(res.body), 'Unexpected error: ' + res.body);
2015-07-08 05:46:58 +08:00
done();
});
});
2019-10-22 01:07:24 +08:00
it('bogus sql raises 200 status code for jsonp', function (done) {
2015-07-08 05:46:58 +08:00
var bogusSqlMapConfig = testClient.singleLayerMapConfig('bogus');
var options = {
method: 'GET',
callbackName: 'test',
headers: {
'Content-Type': 'text/javascript; charset=utf-8'
}
};
2019-10-22 01:07:24 +08:00
testClient.createLayergroup(bogusSqlMapConfig, options, function (err, res) {
2019-10-25 00:38:37 +08:00
assert.ifError(err);
2015-09-17 08:06:32 +08:00
assert.ok(
/^\/\*\*\/ typeof test === 'function' && test\(/.test(res.body),
2019-10-22 01:07:24 +08:00
'Body start expected callback name: ' + res.body
2015-09-17 08:06:32 +08:00
);
2019-10-22 01:07:24 +08:00
assert.ok(/syntax error/.test(res.body), 'Unexpected error: ' + res.body);
2015-07-08 05:46:58 +08:00
done();
});
});
2019-10-22 01:07:24 +08:00
it('query not selecting the_geom raises 200 status code for jsonp instead of 404', function (done) {
2015-07-08 05:46:58 +08:00
var noGeomMapConfig = testClient.singleLayerMapConfig('select null::geometry the_geom_wadus');
var options = {
method: 'GET',
callbackName: 'test',
headers: {
'Content-Type': 'text/javascript; charset=utf-8'
}
};
2019-10-22 01:07:24 +08:00
testClient.createLayergroup(noGeomMapConfig, options, function (err, res) {
2019-10-25 00:38:37 +08:00
assert.ifError(err);
2015-09-17 08:06:32 +08:00
assert.ok(
/^\/\*\*\/ typeof test === 'function' && test\(/.test(res.body),
2019-10-22 01:07:24 +08:00
'Body start expected callback name: ' + res.body
2015-09-17 08:06:32 +08:00
);
2019-10-22 01:07:24 +08:00
assert.ok(/column.*does not exist/.test(res.body), 'Unexpected error: ' + res.body);
2015-07-08 05:46:58 +08:00
done();
});
});
2019-10-22 01:07:24 +08:00
it('query with no geometry field returns 400 status', function (done) {
2015-07-08 05:46:58 +08:00
var noGeometrySqlMapConfig = testClient.singleLayerMapConfig('SELECT 1');
2019-10-22 01:07:24 +08:00
testClient.createLayergroup(noGeometrySqlMapConfig, { statusCode: 400 }, function (err, res) {
2019-10-25 00:38:37 +08:00
assert.ifError(err);
2019-10-22 01:07:24 +08:00
assert.ok(/column.*does not exist/.test(res.body), 'Unexpected error: ' + res.body);
2015-07-08 05:46:58 +08:00
done();
});
});
2019-10-22 01:07:24 +08:00
it('bogus style should raise 400 status', function (done) {
2015-07-08 05:46:58 +08:00
var bogusStyleMapConfig = testClient.defaultTableMapConfig('test_table', '#test_table{xxxxx;}');
testClient.createLayergroup(bogusStyleMapConfig, { method: 'GET', statusCode: 400 }, done);
});
var defaultErrorExpectedResponse = {
status: 400,
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
};
2019-10-22 01:07:24 +08:00
it('should raise 400 error for out of bounds layer index', function (done) {
2015-07-08 05:46:58 +08:00
var mapConfig = testClient.singleLayerMapConfig('select * from test_table', null, null, 'name');
2019-10-22 01:07:24 +08:00
testClient.getGrid(mapConfig, 1, 13, 4011, 3088, defaultErrorExpectedResponse, function (err, res) {
2019-10-25 00:38:37 +08:00
assert.ifError(err);
assert.deepStrictEqual(JSON.parse(res.body).errors, ["Layer '1' not found in layergroup"]);
2015-09-26 01:07:57 +08:00
done();
2015-07-08 05:46:58 +08:00
});
});
2019-10-22 01:07:24 +08:00
/// /////////////////////////////////////////////////////////////////
2015-07-08 05:46:58 +08:00
//
// OPTIONS LAYERGROUP
//
2019-10-22 01:07:24 +08:00
/// /////////////////////////////////////////////////////////////////
2015-07-08 05:46:58 +08:00
2019-10-22 01:07:24 +08:00
it('nonexistent layergroup token error', function (done) {
step(
2019-11-14 02:36:30 +08:00
function doGetTile (err) {
2019-10-22 01:07:24 +08:00
assert.ifError(err);
var next = this;
assert.response(server, {
url: '/api/v1/map/deadbeef/0/0/0/0.grid.json',
method: 'GET',
encoding: 'binary',
headers: {
host: 'localhost'
}
}, {}, function (res, err) { next(err, res); });
},
function checkResponse (err, res) {
assert.ifError(err);
// FIXME: should be 404
assert.strictEqual(res.statusCode, 400, res.statusCode + ':' + res.body);
2019-10-22 01:07:24 +08:00
var parsed = JSON.parse(res.body);
assert.deepStrictEqual(parsed.errors, ["Invalid or nonexistent map configuration token 'deadbeef'"]);
2019-10-22 01:07:24 +08:00
return null;
},
function finish (err) {
done(err);
}
);
2015-07-08 05:46:58 +08:00
});
2019-10-22 01:07:24 +08:00
it('error 400 on json syntax error', function (done) {
var layergroup = {
2015-07-08 05:46:58 +08:00
version: '1.0.1',
layers: [
{
options: {
sql: 'select the_geom from test_table limit 1',
cartocss: '#layer { marker-fill:red }'
}
}
]
};
assert.response(server,
{
2019-10-02 01:34:03 +08:00
url: '/api/v1/map',
2015-07-08 05:46:58 +08:00
method: 'POST',
2019-10-22 01:07:24 +08:00
headers: { 'Content-Type': 'application/json; charset=utf-8' },
2015-07-08 05:46:58 +08:00
data: '{' + JSON.stringify(layergroup)
},
{
status: 400
},
2019-10-22 01:07:24 +08:00
function (res) {
2015-07-08 05:46:58 +08:00
var parsedBody = JSON.parse(res.body);
2017-02-17 20:36:15 +08:00
assert.ok(parsedBody.errors);
assert.strictEqual(parsedBody.errors.length, 1);
2017-02-17 20:36:15 +08:00
assert.ok(parsedBody.errors[0].match(/^SyntaxError: Unexpected token {/));
2015-07-08 05:46:58 +08:00
done();
}
);
});
});