diff --git a/INSTALL.md b/INSTALL.md index cfb6cfc4..751c5ef8 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -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 diff --git a/NEWS.md b/NEWS.md index 3dd16c6f..656b77ed 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,14 @@ # Changelog +## 2.25.3 + + ## 2.25.2 -Released 2016-mm-dd +Released 2016-02-22 +Bug fixes: + - Correct URLs for widgets in named maps #381 ## 2.25.1 diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index 9115646f..020a5744 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -184,6 +184,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); } @@ -257,6 +259,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())); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 4ffc51f5..4a48ec85 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "windshaft-cartodb", - "version": "2.25.2", + "version": "2.25.3", "dependencies": { "body-parser": { "version": "1.14.2", diff --git a/package.json b/package.json index 46f11788..d3deba49 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "windshaft-cartodb", - "version": "2.25.2", + "version": "2.25.3", "description": "A map tile server for CartoDB", "keywords": [ "cartodb" diff --git a/test/acceptance/limits.js b/test/acceptance/limits.js index e7e4a305..ef91dac4 100644 --- a/test/acceptance/limits.js +++ b/test/acceptance/limits.js @@ -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); } diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index a774081d..2dbfbbbd 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -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,38 +190,50 @@ describe(suiteName, function() { }); - it("should include serverMedata in the response", function(done) { - global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } }; - var layergroup = { - version: '1.0.0', - layers: [ - { options: { - sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' + - ' from test_table limit 2', - cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }', - cartocss_version: '2.0.1' - } } - ] - }; + 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: [ + { options: { + sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator' + + ' from test_table limit 2', + cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }', + cartocss_version: '2.0.1' + } } + ] + }; + + step( + function do_create_get() + { + var next = this; + assert.response(server, { + url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), + method: 'GET', + headers: {host: 'localhost'} + }, {}, function(res, err) { next(err, res); }); + }, + function do_check_create(err, res) { + var parsed = JSON.parse(res.body); + keysToDelete['map_cfg|' + LayergroupToken.parse(parsed.layergroupid).token] = 0; + keysToDelete['user:localhost:mapviews:global'] = 5; + assert.ok(_.isEqual(parsed.cdn_url, global.environment.serverMetadata.cdn_url)); + done(); + } + ); + }); - step( - function do_create_get() - { - var next = this; - assert.response(server, { - url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)), - method: 'GET', - headers: {host: 'localhost'} - }, {}, function(res, err) { next(err, res); }); - }, - function do_check_create(err, res) { - var parsed = JSON.parse(res.body); - keysToDelete['map_cfg|' + LayergroupToken.parse(parsed.layergroupid).token] = 0; - keysToDelete['user:localhost:mapviews:global'] = 5; - assert.ok(_.isEqual(parsed.cdn_url, global.environment.serverMetadata.cdn_url)); - 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); } diff --git a/test/acceptance/overviews_queries.js b/test/acceptance/overviews_queries.js index 8024ba72..0434ebfc 100644 --- a/test/acceptance/overviews_queries.js +++ b/test/acceptance/overviews_queries.js @@ -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); }; } diff --git a/test/acceptance/ported/blend.js b/test/acceptance/ported/blend.js index eca436ae..1e844d80 100644 --- a/test/acceptance/ported/blend.js +++ b/test/acceptance/ported/blend.js @@ -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.ok(!err); - done(); - }); + assert.imageBufferIsSimilarToFile(res.body, blendPngFixture(zxy), IMAGE_TOLERANCE_PER_MIL, + function(err) { + assert.ok(!err); + done(); + } + ); }); }); }); diff --git a/test/acceptance/ported/blend_filtering.js b/test/acceptance/ported/blend_filtering.js index c1b11933..dc8cd470 100644 --- a/test/acceptance/ported/blend_filtering.js +++ b/test/acceptance/ported/blend_filtering.js @@ -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.ok(!err); - done(); - }); + assert.imageBufferIsSimilarToFile(res.body, blendPngFixture(filteredLayers), IMG_TOLERANCE_PER_MIL, + function(err) { + assert.ok(!err); + done(); + } + ); }); }); }); diff --git a/test/acceptance/ported/blend_http_fallback.js b/test/acceptance/ported/blend_http_fallback.js index 3c35c5fc..91e832f6 100644 --- a/test/acceptance/ported/blend_http_fallback.js +++ b/test/acceptance/ported/blend_http_fallback.js @@ -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.ok(!err, err); - done(); - }); + assert.imageBufferIsSimilarToFile(res.body, blendPngFixture(filteredLayers), IMG_TOLERANCE_PER_MIL, + function(err) { + assert.ok(!err, err); + done(); + } + ); }); }); }); diff --git a/test/acceptance/ported/external_resources.js b/test/acceptance/ported/external_resources.js index a0affa83..6f73b52e 100644 --- a/test/acceptance/ported/external_resources.js +++ b/test/acceptance/ported/external_resources.js @@ -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); }; } diff --git a/test/acceptance/ported/limits.js b/test/acceptance/ported/limits.js index f032ff3f..c111c87c 100644 --- a/test/acceptance/ported/limits.js +++ b/test/acceptance/ported/limits.js @@ -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) { - finish(function(finishErr) { - done(err || finishErr); - }); - }); + assert.imageBufferIsSimilarToFile(res.body, fixtureImage, IMAGE_EQUALS_TOLERANCE_PER_MIL, + function(err) { + finish(function(finishErr) { + done(err || finishErr); + }); + } + ); }); }); }); diff --git a/test/acceptance/ported/multilayer.js b/test/acceptance/ported/multilayer.js index 7e9b984c..eb337070 100644 --- a/test/acceptance/ported/multilayer.js +++ b/test/acceptance/ported/multilayer.js @@ -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); }); diff --git a/test/acceptance/ported/raster.js b/test/acceptance/ported/raster.js index 00d34509..cd3d43b9 100644 --- a/test/acceptance/ported/raster.js +++ b/test/acceptance/ported/raster.js @@ -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 { diff --git a/test/acceptance/ported/server_gettile.js b/test/acceptance/ported/server_gettile.js index 7dad9aa3..580e8a61 100644 --- a/test/acceptance/ported/server_gettile.js +++ b/test/acceptance/ported/server_gettile.js @@ -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) { - - finish(function(finishErr) { - done(err || finishErr); - }); - }); + assert.imageBufferIsSimilarToFile(res.body, imageFixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, + function(err) { + finish(function(finishErr) { + done(err || finishErr); + }); + } + ); }); }); }); diff --git a/test/acceptance/ported/server_png8_format.js b/test/acceptance/ported/server_png8_format.js index fdd5a131..39c89c66 100644 --- a/test/acceptance/ported/server_png8_format.js +++ b/test/acceptance/ported/server_png8_format.js @@ -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; diff --git a/test/acceptance/ported/torque_png.js b/test/acceptance/ported/torque_png.js index fef2c621..69eaadab 100644 --- a/test/acceptance/ported/torque_png.js +++ b/test/acceptance/ported/torque_png.js @@ -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.ok(!err); - done(); - }); + assert.imageBufferIsSimilarToFile(res.body, torquePngFixture(zxy), IMAGE_TOLERANCE_PER_MIL, + function(err) { + assert.ok(!err); + done(); + } + ); }); }); }); diff --git a/test/acceptance/ported/wrap.js b/test/acceptance/ported/wrap.js index 1f46b5c3..64a8e2f4 100644 --- a/test/acceptance/ported/wrap.js +++ b/test/acceptance/ported/wrap.js @@ -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.ok(!err); - done(); - }); + assert.imageBufferIsSimilarToFile(res.body, blendPngFixture(fixtureZxy), IMG_TOLERANCE_PER_MIL, + function(err) { + assert.ok(!err); + done(); + } + ); }); }); }); diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index 6326381d..ae997ca8 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -313,51 +313,63 @@ describe('template_api', function() { }); }); - it("instance endpoint should return server metadata", function(done){ - global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } }; - var tmpl = _.clone(template_acceptance1); - tmpl.name = "rambotemplate2"; + describe('server-metadata', function() { + var serverMetadata; + beforeEach(function() { + serverMetadata = global.environment.serverMetadata; + global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } }; + }); - step(function postTemplate1() { - var next = this; - var post_request = { - url: '/api/v1/map/named?api_key=1234', - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/json' }, - data: JSON.stringify(tmpl) - }; - assert.response(server, post_request, {}, function(res) { - next(null, res); - }); - }, - function testCORS() { - var next = this; - assert.response(server, { - url: '/api/v1/map/named/' + tmpl.name, - method: 'POST', - headers: {host: 'localhost', 'Content-Type': 'application/json' } - },{ - status: 200 - }, function(res) { - var parsed = JSON.parse(res.body); - keysToDelete['map_cfg|' + LayergroupToken.parse(parsed.layergroupid).token] = 0; - keysToDelete['user:localhost:mapviews:global'] = 5; - assert.ok(_.isEqual(parsed.cdn_url, global.environment.serverMetadata.cdn_url)); - next(null); - }); - }, - function deleteTemplate(err) { - assert.ifError(err); - var del_request = { - url: '/api/v1/map/named/' + tmpl.name + '?api_key=1234', - method: 'DELETE', - headers: {host: 'localhost', 'Content-Type': 'application/json' } - }; - assert.response(server, del_request, {}, function() { - done(); - }); - } - ); + afterEach(function() { + global.environment.serverMetadata = serverMetadata; + }); + + + it("instance endpoint should return server metadata", function(done){ + var tmpl = _.clone(template_acceptance1); + tmpl.name = "rambotemplate2"; + + step(function postTemplate1() { + var next = this; + var post_request = { + url: '/api/v1/map/named?api_key=1234', + method: 'POST', + headers: {host: 'localhost', 'Content-Type': 'application/json' }, + data: JSON.stringify(tmpl) + }; + assert.response(server, post_request, {}, function(res) { + next(null, res); + }); + }, + function testCORS() { + var next = this; + assert.response(server, { + url: '/api/v1/map/named/' + tmpl.name, + method: 'POST', + headers: {host: 'localhost', 'Content-Type': 'application/json' } + },{ + status: 200 + }, function(res) { + var parsed = JSON.parse(res.body); + keysToDelete['map_cfg|' + LayergroupToken.parse(parsed.layergroupid).token] = 0; + keysToDelete['user:localhost:mapviews:global'] = 5; + assert.ok(_.isEqual(parsed.cdn_url, global.environment.serverMetadata.cdn_url)); + next(null); + }); + }, + function deleteTemplate(err) { + assert.ifError(err); + var del_request = { + url: '/api/v1/map/named/' + tmpl.name + '?api_key=1234', + method: 'DELETE', + headers: {host: 'localhost', 'Content-Type': 'application/json' } + }; + assert.response(server, del_request, {}, function() { + done(); + }); + } + ); + }); }); diff --git a/test/acceptance/widgets/named-maps.js b/test/acceptance/widgets/named-maps.js index 4af90245..ee40d1ce 100644 --- a/test/acceptance/widgets/named-maps.js +++ b/test/acceptance/widgets/named-maps.js @@ -1,6 +1,9 @@ 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'); @@ -15,6 +18,7 @@ describe('named-maps widgets', function() { var widgetsTemplateName = 'widgets-template'; var layergroupid; + var layergroup; var keysToDelete; beforeEach(function(done) { @@ -33,6 +37,13 @@ describe('named-maps widgets', function() { 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: { @@ -105,12 +116,11 @@ describe('named-maps widgets', function() { function fetchTile(err, res) { assert.ifError(err); - var parsed = JSON.parse(res.body); - assert.ok( - parsed.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from response body: " + res.body); - layergroupid = parsed.layergroupid; + layergroup = JSON.parse(res.body); + assert.ok(layergroup.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from: " + res.body); + layergroupid = layergroup.layergroupid; - keysToDelete['map_cfg|' + LayergroupToken.parse(parsed.layergroupid).token] = 0; + keysToDelete['map_cfg|' + LayergroupToken.parse(layergroup.layergroupid).token] = 0; keysToDelete['user:localhost:mapviews:global'] = 5; return done(); @@ -171,6 +181,49 @@ describe('named-maps widgets', function() { ); } + 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) { diff --git a/test/support/assert.js b/test/support/assert.js index 3e66265b..a53d6fbf 100644 --- a/test/support/assert.js +++ b/test/support/assert.js @@ -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); + var referenceImageFilePath = path.resolve(referenceImageRelativeFilePath); + var referenceImageBuffer = fs.readFileSync(referenceImageFilePath, { encoding: null }); + + assert.imageBuffersAreSimilar(buffer, referenceImageBuffer, tolerance, callback); +}; + +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')); + + imagesAreSimilar(testImage, referenceImage, tolerance, callback); +}; + +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 })); + + imagesAreSimilar(testImage, referenceImage, tolerance, function(err) { + if (err) { + var testImageFilePath = randomImagePath(); + testImage.save(testImageFilePath); + } callback(err); }); }; -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'); - - imageFilesAreEqual(imageFilePathA, imageFilePathB, tolerance, function(err, similarity) { - callback(err, [imageFilePathA, imageFilePathB], similarity); - }); -}; - -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; -} - -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 - ); - - exec(imageMagickCmd, function(err, stdout, stderr) { - if (err) { - fs.unlinkSync(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 diff --git a/test/support/test_helper.js b/test/support/test_helper.js index de0f7822..de9a6e3c 100644 --- a/test/support/test_helper.js +++ b/test/support/test_helper.js @@ -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); });