Merge branch 'master' of github.com:CartoDB/Windshaft-cartodb into analysis-layers
This commit is contained in:
commit
b9d2e297b6
@ -16,10 +16,6 @@ Make sure that you have the requirements needed. These are
|
||||
- CartoDB 0.9.5+ (for `CDB_QueryTables`)
|
||||
- Varnish (http://www.varnish-cache.org)
|
||||
|
||||
- For running the testsuite
|
||||
- ImageMagick (http://www.imagemagick.org)
|
||||
|
||||
|
||||
On Ubuntu 14.04 the dependencies can be installed with
|
||||
|
||||
```shell
|
||||
|
21
NEWS.md
21
NEWS.md
@ -1,8 +1,27 @@
|
||||
# Changelog
|
||||
|
||||
## 2.26.0
|
||||
|
||||
Released 2016-mm-dd
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [1.13.0](https://github.com/CartoDB/Windshaft/releases/tag/1.13.0)
|
||||
|
||||
|
||||
## 2.25.2
|
||||
|
||||
Released 2016-02-22
|
||||
|
||||
Bug fixes:
|
||||
- Correct URLs for widgets in named maps #381
|
||||
|
||||
|
||||
## 2.25.1
|
||||
|
||||
Released 2016-mm-dd
|
||||
Released 2016-02-22
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [1.11.1](https://github.com/CartoDB/Windshaft/releases/tag/1.11.1)
|
||||
|
||||
|
||||
## 2.25.0
|
||||
|
@ -207,6 +207,8 @@ MapController.prototype.create = function(req, res, prepareConfigFn) {
|
||||
if (err) {
|
||||
self.sendError(req, res, err, 'ANONYMOUS LAYERGROUP');
|
||||
} else {
|
||||
addWidgetsUrl(req.context.user, layergroup);
|
||||
|
||||
res.set('X-Layergroup-Id', layergroup.layergroupid);
|
||||
self.send(req, res, layergroup, 200);
|
||||
}
|
||||
@ -281,6 +283,8 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
|
||||
var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0, 8);
|
||||
layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid;
|
||||
|
||||
addWidgetsUrl(req.context.user, layergroup);
|
||||
|
||||
res.set('X-Layergroup-Id', layergroup.layergroupid);
|
||||
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, mapConfigProvider.getTemplateName()));
|
||||
|
||||
@ -364,9 +368,6 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, la
|
||||
layergroup.layergroupid = layergroup.layergroupid + ':' + result.lastUpdatedTime;
|
||||
layergroup.last_updated = new Date(result.lastUpdatedTime).toISOString();
|
||||
|
||||
// TODO this should take into account several URL patterns
|
||||
addWidgetsUrl(username, layergroup);
|
||||
|
||||
if (req.method === 'GET') {
|
||||
var tableCacheEntry = new TablesCacheEntry(result.affectedTables);
|
||||
var ttl = global.environment.varnish.layergroupTtl || 86400;
|
||||
|
1457
npm-shrinkwrap.json
generated
1457
npm-shrinkwrap.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "windshaft-cartodb",
|
||||
"version": "2.25.1",
|
||||
"version": "2.26.0",
|
||||
"description": "A map tile server for CartoDB",
|
||||
"keywords": [
|
||||
"cartodb"
|
||||
@ -26,7 +26,7 @@
|
||||
"node-statsd": "~0.0.7",
|
||||
"underscore" : "~1.6.0",
|
||||
"dot": "~1.0.2",
|
||||
"windshaft": "1.11.0",
|
||||
"windshaft": "1.13.0",
|
||||
"step": "~0.0.6",
|
||||
"queue-async": "~1.0.7",
|
||||
"request": "~2.62.0",
|
||||
|
@ -292,7 +292,8 @@ describe('render limits', function() {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
assert.imageEqualsFile(res.body, './test/fixtures/render-timeout-fallback.png', 25,
|
||||
var referenceImagePath = './test/fixtures/render-timeout-fallback.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath, 25,
|
||||
function(imgErr/*, similarity*/) {
|
||||
done(imgErr);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ describe(suiteName, function() {
|
||||
' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
}
|
||||
|
||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png',
|
||||
assert.imageBufferIsSimilarToFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png',
|
||||
IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL, function(err/*, similarity*/) {
|
||||
next(err);
|
||||
}
|
||||
@ -190,8 +190,18 @@ describe(suiteName, function() {
|
||||
});
|
||||
|
||||
|
||||
it("should include serverMedata in the response", function(done) {
|
||||
describe('server-metadata', function() {
|
||||
var serverMetadata;
|
||||
beforeEach(function() {
|
||||
serverMetadata = global.environment.serverMetadata;
|
||||
global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } };
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
global.environment.serverMetadata = serverMetadata;
|
||||
});
|
||||
|
||||
it("should include serverMedata in the response", function(done) {
|
||||
var layergroup = {
|
||||
version: '1.0.0',
|
||||
layers: [
|
||||
@ -224,6 +234,8 @@ describe(suiteName, function() {
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
it("get creation requests has cache", function(done) {
|
||||
|
||||
@ -392,7 +404,8 @@ describe(suiteName, function() {
|
||||
' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
}
|
||||
|
||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
var referenceImagePath = 'test/fixtures/test_multilayer_bbox.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath, IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err/*, similarity*/) {
|
||||
next(err);
|
||||
});
|
||||
@ -431,7 +444,8 @@ describe(suiteName, function() {
|
||||
' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
||||
}
|
||||
|
||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
var referenceImagePath = 'test/fixtures/test_multilayer_bbox.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath, IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err/*, similarity*/) {
|
||||
next(err);
|
||||
});
|
||||
@ -1007,7 +1021,7 @@ describe(suiteName, function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png',
|
||||
assert.imageBufferIsSimilarToFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png',
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err/*, similarity*/) {
|
||||
next(err);
|
||||
}
|
||||
|
@ -70,8 +70,7 @@ describe('tests from old api translated to multilayer', function() {
|
||||
},
|
||||
function(res) {
|
||||
var parsed = JSON.parse(res.body);
|
||||
assert.ok(parsed.errors[0].match(/^style0/));
|
||||
assert.ok(parsed.errors[0].match(/missing closing/));
|
||||
assert.ok(parsed.errors[0].match(/<css input>:1:1: Unclosed block/));
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
@ -30,7 +30,8 @@ describe('overviews_queries', function() {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
assert.imageEqualsFile(tile.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
|
||||
var referenceImagePath = './test/fixtures/' + fixture;
|
||||
assert.imageBufferIsSimilarToFile(tile.body, referenceImagePath, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -95,10 +95,12 @@ describe('blend png renderer', function() {
|
||||
var zxy = [tileRequest.z, tileRequest.x, tileRequest.y];
|
||||
it('tile all/' + zxy.join('/') + '.png', function (done) {
|
||||
testClient.getTileLayer(plainTorqueMapConfig(testScenario.plainColor), tileRequest, function(err, res) {
|
||||
assert.imageEqualsFile(res.body, blendPngFixture(zxy), IMAGE_TOLERANCE_PER_MIL, function(err) {
|
||||
assert.imageBufferIsSimilarToFile(res.body, blendPngFixture(zxy), IMAGE_TOLERANCE_PER_MIL,
|
||||
function(err) {
|
||||
assert.ok(!err);
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -156,10 +156,12 @@ describe('blend layer filtering', function() {
|
||||
|
||||
it('should filter on ' + layerFilter + '/1/0/0.png', function (done) {
|
||||
testClient.getTileLayer(mapConfig, tileRequest, function(err, res) {
|
||||
assert.imageEqualsFile(res.body, blendPngFixture(filteredLayers), IMG_TOLERANCE_PER_MIL, function(err) {
|
||||
assert.imageBufferIsSimilarToFile(res.body, blendPngFixture(filteredLayers), IMG_TOLERANCE_PER_MIL,
|
||||
function(err) {
|
||||
assert.ok(!err);
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -111,10 +111,12 @@ describe('blend http fallback', function() {
|
||||
|
||||
it('should fallback on http error while blending layers ' + layerFilter + '/1/0/0.png', function (done) {
|
||||
testClient.getTileLayer(mapConfig, tileRequest, function(err, res) {
|
||||
assert.imageEqualsFile(res.body, blendPngFixture(filteredLayers), IMG_TOLERANCE_PER_MIL, function(err) {
|
||||
assert.imageBufferIsSimilarToFile(res.body, blendPngFixture(filteredLayers), IMG_TOLERANCE_PER_MIL,
|
||||
function(err) {
|
||||
assert.ok(!err, err);
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -57,7 +57,8 @@ describe('external resources', function() {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
assert.imageEqualsFile(res.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
|
||||
var referenceImagePath = './test/fixtures/' + fixture;
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -84,11 +84,13 @@ describe.skip('render limits', function() {
|
||||
testClient.withLayergroup(slowQueryMapConfig, options, function(err, requestTile, finish) {
|
||||
var tileUrl = '/0/0/0.png';
|
||||
requestTile(tileUrl, options, function(err, res) {
|
||||
assert.imageEqualsFile(res.body, fixtureImage, IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
assert.imageBufferIsSimilarToFile(res.body, fixtureImage, IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err) {
|
||||
finish(function(finishErr) {
|
||||
done(err || finishErr);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -117,7 +117,8 @@ describe('multilayer', function() {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
checkCORSHeaders(res);
|
||||
assert.imageEqualsFile(res.body, './test/fixtures/test_bigpoint_red.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
var referenceImagePath = './test/fixtures/test_bigpoint_red.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath, IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err) {
|
||||
next(err);
|
||||
});
|
||||
@ -191,7 +192,8 @@ describe('multilayer', function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer1.png',
|
||||
var referenceImagePath = './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer1.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath,
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
next(err);
|
||||
});
|
||||
@ -302,7 +304,8 @@ describe('multilayer', function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer1.png',
|
||||
var referenceImagePath = './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer1.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath,
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
next(err);
|
||||
});
|
||||
@ -425,7 +428,8 @@ describe('multilayer', function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer1.png',
|
||||
var referenceImagePath = './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer1.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath,
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
next(err);
|
||||
});
|
||||
@ -541,7 +545,8 @@ describe('multilayer', function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer1.png',
|
||||
var referenceImagePath = './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer1.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath,
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
next(err);
|
||||
});
|
||||
@ -727,7 +732,8 @@ describe('multilayer', function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer2.png',
|
||||
var referenceImagePath = './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer2.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath,
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
next(err);
|
||||
});
|
||||
@ -761,7 +767,8 @@ describe('multilayer', function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer3.png',
|
||||
var referenceImagePath = './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer3.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath,
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
next(err);
|
||||
});
|
||||
@ -856,7 +863,8 @@ describe('multilayer', function() {
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
assert.imageEqualsFile(res.body, './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer4.png',
|
||||
var referenceImagePath = './test/acceptance/ported/fixtures/test_table_0_0_0_multilayer4.png';
|
||||
assert.imageBufferIsSimilarToFile(res.body, referenceImagePath,
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
next(err);
|
||||
});
|
||||
@ -1259,7 +1267,7 @@ describe('multilayer', function() {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.equal(res.headers['content-type'], "image/png");
|
||||
checkCORSHeaders(res);
|
||||
assert.imageEqualsFile(res.body, './test/fixtures/test_bigpoint_red.png',
|
||||
assert.imageBufferIsSimilarToFile(res.body, './test/fixtures/test_bigpoint_red.png',
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
next(err);
|
||||
});
|
||||
|
@ -87,7 +87,7 @@ describe('raster', function() {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
assert.deepEqual(res.headers['content-type'], "image/png");
|
||||
var next = this;
|
||||
assert.imageEqualsFile(res.body,
|
||||
assert.imageBufferIsSimilarToFile(res.body,
|
||||
'./test/fixtures/raster_gray_rect.png',
|
||||
IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
try {
|
||||
|
@ -34,7 +34,9 @@ describe('server_gettile', function() {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
assert.imageEqualsFile(res.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
|
||||
assert.imageBufferIsSimilarToFile(
|
||||
res.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@ -113,12 +115,13 @@ describe('server_gettile', function() {
|
||||
assert.ok(res.headers.hasOwnProperty('x-windshaft-cache'), "Did not hit renderer cache on second time");
|
||||
assert.ok(res.headers['x-windshaft-cache'] >= 0);
|
||||
|
||||
assert.imageEqualsFile(res.body, imageFixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
|
||||
|
||||
assert.imageBufferIsSimilarToFile(res.body, imageFixture, IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err) {
|
||||
finish(function(finishErr) {
|
||||
done(err || finishErr);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -108,7 +108,7 @@ describe('server_png8_format', function() {
|
||||
assert.equal(responsePng8.headers['content-type'], "image/png");
|
||||
bufferPng8 = responsePng8.body;
|
||||
assert.ok(bufferPng8.length < bufferPng32.length);
|
||||
assert.imageBuffersAreEqual(bufferPng32, bufferPng8, IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
assert.imageBuffersAreSimilar(bufferPng32, bufferPng8, IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||
function(err, imagePaths, similarity) {
|
||||
|
||||
keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
||||
|
@ -83,10 +83,12 @@ describe('torque png renderer', function() {
|
||||
var zxy = [z, x, y];
|
||||
it('tile ' + zxy.join('/') + '.torque.png', function (done) {
|
||||
testClient.getTileLayer(torquePngPointsMapConfig, tileRequest, function(err, res) {
|
||||
assert.imageEqualsFile(res.body, torquePngFixture(zxy), IMAGE_TOLERANCE_PER_MIL, function(err) {
|
||||
assert.imageBufferIsSimilarToFile(res.body, torquePngFixture(zxy), IMAGE_TOLERANCE_PER_MIL,
|
||||
function(err) {
|
||||
assert.ok(!err);
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -107,10 +107,12 @@ describe('wrap x coordinate', function() {
|
||||
var fixtureZxy = [testScenario.fixture.z, testScenario.fixture.x, testScenario.fixture.y];
|
||||
it('tile all/' + zxy.join('/') + '.png', function (done) {
|
||||
testClient.getTileLayer(plainTorqueMapConfig(testScenario.plainColor), tileRequest, function(err, res) {
|
||||
assert.imageEqualsFile(res.body, blendPngFixture(fixtureZxy), IMG_TOLERANCE_PER_MIL, function(err) {
|
||||
assert.imageBufferIsSimilarToFile(res.body, blendPngFixture(fixtureZxy), IMG_TOLERANCE_PER_MIL,
|
||||
function(err) {
|
||||
assert.ok(!err);
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -313,8 +313,19 @@ describe('template_api', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it("instance endpoint should return server metadata", function(done){
|
||||
describe('server-metadata', function() {
|
||||
var serverMetadata;
|
||||
beforeEach(function() {
|
||||
serverMetadata = global.environment.serverMetadata;
|
||||
global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } };
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
global.environment.serverMetadata = serverMetadata;
|
||||
});
|
||||
|
||||
|
||||
it("instance endpoint should return server metadata", function(done){
|
||||
var tmpl = _.clone(template_acceptance1);
|
||||
tmpl.name = "rambotemplate2";
|
||||
|
||||
@ -359,6 +370,7 @@ describe('template_api', function() {
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
250
test/acceptance/widgets/named-maps.js
Normal file
250
test/acceptance/widgets/named-maps.js
Normal file
@ -0,0 +1,250 @@
|
||||
var assert = require('../../support/assert');
|
||||
var step = require('step');
|
||||
|
||||
var url = require('url');
|
||||
var queue = require('queue-async');
|
||||
|
||||
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 LayergroupToken = require('../../../lib/cartodb/models/layergroup_token');
|
||||
|
||||
describe('named-maps widgets', 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: {
|
||||
sql: "select * from populated_places_simple_reduced_private",
|
||||
cartocss: '#layer { marker-fill: blue; }',
|
||||
cartocss_version: '2.3.0',
|
||||
widgets: {
|
||||
pop_max_formula_sum: {
|
||||
type: 'formula',
|
||||
options: {
|
||||
column: 'pop_max',
|
||||
operation: 'sum'
|
||||
}
|
||||
},
|
||||
country_places_count: {
|
||||
type: 'aggregation',
|
||||
options: {
|
||||
column: 'adm0_a3',
|
||||
aggregation: 'count'
|
||||
}
|
||||
},
|
||||
pop_max: {
|
||||
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'
|
||||
},
|
||||
data: JSON.stringify(widgetsTemplate)
|
||||
},
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res, err) {
|
||||
next(err, res);
|
||||
}
|
||||
);
|
||||
},
|
||||
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 fetchTile(err, res) {
|
||||
assert.ifError(err);
|
||||
|
||||
layergroup = JSON.parse(res.body);
|
||||
assert.ok(layergroup.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from: " + res.body);
|
||||
layergroupid = layergroup.layergroupid;
|
||||
|
||||
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);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
function getWidget(widgetName, callback) {
|
||||
assert.response(
|
||||
server,
|
||||
{
|
||||
url: '/api/v1/map/' + layergroupid + '/0/widget/' + widgetName,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: username
|
||||
}
|
||||
},
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res, err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
return callback(err, res, parsedBody);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
it('should be able to retrieve widgets from all URLs', function(done) {
|
||||
var widgetsPaths = layergroup.metadata.layers.reduce(function(paths, layer) {
|
||||
var widgets = layer.widgets || {};
|
||||
Object.keys(widgets).forEach(function(widget) {
|
||||
paths.push(url.parse(widgets[widget].url.http).path);
|
||||
});
|
||||
|
||||
return paths;
|
||||
}, []);
|
||||
|
||||
var widgetsQueue = queue(widgetsPaths.length);
|
||||
|
||||
widgetsPaths.forEach(function(path) {
|
||||
widgetsQueue.defer(function(path, done) {
|
||||
assert.response(
|
||||
server,
|
||||
{
|
||||
url: path,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: username
|
||||
}
|
||||
},
|
||||
{
|
||||
status: 200
|
||||
},
|
||||
function(res, err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
return done(null, parsedBody);
|
||||
}
|
||||
);
|
||||
}, path);
|
||||
});
|
||||
|
||||
widgetsQueue.awaitAll(function(err, results) {
|
||||
assert.equal(results.length, 3);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("should retrieve aggregation", function(done) {
|
||||
getWidget('country_places_count', function(err, response, aggregation) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
assert.equal(aggregation.type, 'aggregation');
|
||||
assert.equal(aggregation.max, 769);
|
||||
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should retrieve histogram", function(done) {
|
||||
getWidget('pop_max', function(err, response, histogram) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
assert.equal(histogram.type, 'histogram');
|
||||
assert.equal(histogram.bin_width, 743250);
|
||||
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -1,7 +1,6 @@
|
||||
// Cribbed from the ever prolific Konstantin Kaefer
|
||||
// https://github.com/mapbox/tilelive-mapnik/blob/master/test/support/assert.js
|
||||
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var util = require('util');
|
||||
@ -13,7 +12,7 @@ var request = require('request');
|
||||
var assert = module.exports = exports = require('assert');
|
||||
|
||||
/**
|
||||
* Takes an image data as an input and an image path and compare them using ImageMagick fuzz algorithm, if case the
|
||||
* Takes an image data as an input and an image path and compare them using mapnik.Image.compare mechanism, in case the
|
||||
* similarity is not within the tolerance limit it will callback with an error.
|
||||
*
|
||||
* @param buffer The image data to compare from
|
||||
@ -22,70 +21,39 @@ var assert = module.exports = exports = require('assert');
|
||||
* @param {function} callback Will call to home with null in case there is no error, otherwise with the error itself
|
||||
* @see FUZZY in http://www.imagemagick.org/script/command-line-options.php#metric
|
||||
*/
|
||||
assert.imageEqualsFile = function(buffer, referenceImageRelativeFilePath, tolerance, callback) {
|
||||
assert.imageBufferIsSimilarToFile = function(buffer, referenceImageRelativeFilePath, tolerance, callback) {
|
||||
callback = callback || function(err) { assert.ifError(err); };
|
||||
var referenceImageFilePath = path.resolve(referenceImageRelativeFilePath),
|
||||
testImageFilePath = createImageFromBuffer(buffer, 'test');
|
||||
|
||||
imageFilesAreEqual(testImageFilePath, referenceImageFilePath, tolerance, function(err) {
|
||||
fs.unlinkSync(testImageFilePath);
|
||||
callback(err);
|
||||
});
|
||||
var referenceImageFilePath = path.resolve(referenceImageRelativeFilePath);
|
||||
var referenceImageBuffer = fs.readFileSync(referenceImageFilePath, { encoding: null });
|
||||
|
||||
assert.imageBuffersAreSimilar(buffer, referenceImageBuffer, tolerance, callback);
|
||||
};
|
||||
|
||||
assert.imageBuffersAreEqual = function(bufferA, bufferB, tolerance, callback) {
|
||||
var randStr = (Math.random() * 1e16).toString().substring(0, 8);
|
||||
var imageFilePathA = createImageFromBuffer(bufferA, randStr + '-a'),
|
||||
imageFilePathB = createImageFromBuffer(bufferB, randStr + '-b');
|
||||
assert.imageBuffersAreSimilar = function(bufferA, bufferB, tolerance, callback) {
|
||||
var testImage = mapnik.Image.fromBytes(Buffer.isBuffer(bufferA) ? bufferA : new Buffer(bufferA, 'binary'));
|
||||
var referenceImage = mapnik.Image.fromBytes(Buffer.isBuffer(bufferB) ? bufferB : new Buffer(bufferB, 'binary'));
|
||||
|
||||
imageFilesAreEqual(imageFilePathA, imageFilePathB, tolerance, function(err, similarity) {
|
||||
callback(err, [imageFilePathA, imageFilePathB], similarity);
|
||||
});
|
||||
imagesAreSimilar(testImage, referenceImage, tolerance, callback);
|
||||
};
|
||||
|
||||
function createImageFromBuffer(buffer, nameHint) {
|
||||
var imageFilePath = path.resolve('test/results/png/image-' + nameHint + '-' + Date.now() + '.png');
|
||||
var err = fs.writeFileSync(imageFilePath, buffer, 'binary');
|
||||
assert.ifError(err);
|
||||
return imageFilePath;
|
||||
}
|
||||
assert.imageIsSimilarToFile = function(testImage, referenceImageRelativeFilePath, tolerance, callback) {
|
||||
callback = callback || function(err) { assert.ifError(err); };
|
||||
|
||||
function imageFilesAreEqual(testImageFilePath, referenceImageFilePath, tolerance, callback) {
|
||||
var resultFilePath = path.resolve(util.format('/tmp/windshaft-result-%s-diff.png', Date.now()));
|
||||
var imageMagickCmd = util.format(
|
||||
'compare -metric fuzz "%s" "%s" "%s"',
|
||||
testImageFilePath, referenceImageFilePath, resultFilePath
|
||||
);
|
||||
var referenceImageFilePath = path.resolve(referenceImageRelativeFilePath);
|
||||
|
||||
exec(imageMagickCmd, function(err, stdout, stderr) {
|
||||
var referenceImage = mapnik.Image.fromBytes(fs.readFileSync(referenceImageFilePath, { encoding: null }));
|
||||
|
||||
imagesAreSimilar(testImage, referenceImage, tolerance, function(err) {
|
||||
if (err) {
|
||||
fs.unlinkSync(testImageFilePath);
|
||||
var testImageFilePath = randomImagePath();
|
||||
testImage.save(testImageFilePath);
|
||||
}
|
||||
callback(err);
|
||||
} else {
|
||||
stderr = stderr.trim();
|
||||
var metrics = stderr.match(/([0-9]*) \((.*)\)/);
|
||||
if ( ! metrics ) {
|
||||
callback(new Error("No match for " + stderr));
|
||||
return;
|
||||
}
|
||||
var similarity = parseFloat(metrics[2]),
|
||||
tolerancePerMil = (tolerance / 1000);
|
||||
if (similarity > tolerancePerMil) {
|
||||
err = new Error(util.format(
|
||||
'Images %s and %s are not equal (got %d similarity, expected %d). Result %s',
|
||||
testImageFilePath, referenceImageFilePath, similarity, tolerancePerMil, resultFilePath)
|
||||
);
|
||||
err.similarity = similarity;
|
||||
callback(err, similarity);
|
||||
} else {
|
||||
fs.unlinkSync(resultFilePath);
|
||||
callback(null, similarity);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
assert.imagesAreSimilar = function(testImage, referenceImage, tolerance, callback) {
|
||||
function imagesAreSimilar(testImage, referenceImage, tolerance, callback) {
|
||||
if (testImage.width() !== referenceImage.width() || testImage.height() !== referenceImage.height()) {
|
||||
return callback(new Error('Images are not the same size'));
|
||||
}
|
||||
@ -103,27 +71,10 @@ assert.imagesAreSimilar = function(testImage, referenceImage, tolerance, callbac
|
||||
} else {
|
||||
callback(null, similarity);
|
||||
}
|
||||
};
|
||||
|
||||
assert.imageIsSimilarToFile = function(testImage, referenceImageRelativeFilePath, tolerance, callback) {
|
||||
callback = callback || function(err) { assert.ifError(err); };
|
||||
|
||||
var referenceImageFilePath = path.resolve(referenceImageRelativeFilePath);
|
||||
|
||||
var referenceImage = mapnik.Image.fromBytes(fs.readFileSync(referenceImageFilePath, { encoding: null }));
|
||||
|
||||
assert.imagesAreSimilar(testImage, referenceImage, tolerance, function(err) {
|
||||
if (err) {
|
||||
var testImageFilePath = randomImagePath();
|
||||
testImage.save(testImageFilePath);
|
||||
}
|
||||
callback(err);
|
||||
});
|
||||
};
|
||||
|
||||
function randomImagePath(nameHint) {
|
||||
nameHint = nameHint || 'test';
|
||||
return path.resolve('test/results/png/image-' + nameHint + '-' + Date.now() + '.png');
|
||||
function randomImagePath() {
|
||||
return path.resolve('test/results/png/image-test-' + Date.now() + '.png');
|
||||
}
|
||||
|
||||
// jshint maxcomplexity:9
|
||||
|
@ -7385,3 +7385,8 @@ GRANT ALL ON TABLE populated_places_simple_reduced TO :TESTUSER;
|
||||
GRANT SELECT ON TABLE populated_places_simple_reduced TO :PUBLICUSER;
|
||||
|
||||
VACUUM ANALYZE populated_places_simple_reduced;
|
||||
|
||||
create table populated_places_simple_reduced_private AS
|
||||
select * from populated_places_simple_reduced;
|
||||
|
||||
GRANT ALL ON TABLE populated_places_simple_reduced_private TO :TESTUSER;
|
||||
|
@ -74,6 +74,14 @@ function checkSurrogateKey(res, expectedKey) {
|
||||
assert.deepEqual(keys, expectedKeys);
|
||||
}
|
||||
|
||||
var redisClient;
|
||||
|
||||
beforeEach(function() {
|
||||
if (!redisClient) {
|
||||
redisClient = redis.createClient(global.environment.redis.port);
|
||||
}
|
||||
});
|
||||
|
||||
//global afterEach to capture test suites that leave keys in redis
|
||||
afterEach(function(done) {
|
||||
|
||||
@ -110,7 +118,6 @@ afterEach(function(done) {
|
||||
}
|
||||
|
||||
Object.keys(databasesTasks).forEach(function(db) {
|
||||
var redisClient = redis.createClient(global.environment.redis.port);
|
||||
redisClient.select(db, function() {
|
||||
// Check that we start with an empty redis db
|
||||
redisClient.keys("*", function(err, keys) {
|
||||
@ -137,6 +144,7 @@ function deleteRedisKeys(keysToDelete, callback) {
|
||||
var redisClient = redis.createClient(global.environment.redis.port);
|
||||
redisClient.select(keysToDelete[k], function() {
|
||||
redisClient.del(k, function(err, deletedKeysCount) {
|
||||
redisClient.quit();
|
||||
assert.notStrictEqual(deletedKeysCount, 0, 'No KEYS deleted for: [db=' + keysToDelete[k] + ']' + k);
|
||||
taskDone(k);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user