'use strict'; require('../../support/test-helper'); var assert = require('../../support/assert'); var TestClient = require('../../support/test-client'); describe('analysis-layers error cases', function () { function createMapConfig (layers, dataviews, analysis) { return { version: '1.5.0', layers: layers, dataviews: dataviews || {}, analyses: analysis || [] }; } var ERROR_RESPONSE = { status: 400, headers: { 'Content-Type': 'application/json; charset=utf-8' } }; var AUTH_ERROR_RESPONSE = { status: 403, headers: { 'Content-Type': 'application/json; charset=utf-8' } }; it('should handle missing analysis nodes for layers', function (done) { var mapConfig = createMapConfig( [ { type: 'cartodb', options: { source: { id: 'INVALID-SOURCE-ID' }, cartocss: '#polygons { polygon-fill: red; }', cartocss_version: '2.3.0' } } ], {}, [ { id: 'HEAD', type: 'buffer', params: { source: { id: '2570e105-7b37-40d2-bdf4-1af889598745', type: 'source', params: { query: 'select * from populated_places_simple_reduced' } }, radius: 50000 } } ] ); var testClient = new TestClient(mapConfig, 1234); testClient.getLayergroup({ response: ERROR_RESPONSE }, function (err, layergroupResult) { assert.ok(!err, err); assert.strictEqual(layergroupResult.errors.length, 1); assert.strictEqual(layergroupResult.errors[0], 'Missing analysis node.id="INVALID-SOURCE-ID" for layer=0'); testClient.drain(done); }); }); it('should handle missing analyses when layers point to nonexistent one', function (done) { var mapConfig = createMapConfig( [ { type: 'http', options: { urlTemplate: 'http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png', subdomains: 'abcd' } }, { type: 'cartodb', options: { source: { id: 'ID-FOR-NONEXISTENT-ANALYSIS' }, cartocss: '#polygons { polygon-fill: red; }', cartocss_version: '2.3.0' } } ] ); var testClient = new TestClient(mapConfig, 1234); testClient.getLayergroup({ response: ERROR_RESPONSE }, function (err, layergroupResult) { assert.ok(!err, err); assert.strictEqual(layergroupResult.errors.length, 1); assert.strictEqual( layergroupResult.errors[0], 'Missing analysis node.id="ID-FOR-NONEXISTENT-ANALYSIS" for layer=1' ); testClient.drain(done); }); }); it('should handle missing analyses when dataviews point to nonexistent one', function (done) { var mapConfig = createMapConfig( [ { type: 'http', options: { urlTemplate: 'http://{s}.basemaps.cartocdn.com/light_only_labels/{z}/{x}/{y}.png', subdomains: 'abcd' } }, { type: 'cartodb', options: { sql: 'select * from populated_places_simple_reduced', cartocss: '#polygons { polygon-fill: red; }', cartocss_version: '2.3.0' } } ], { pop_max_histogram: { source: { id: 'ID-FOR-NONEXISTENT-ANALYSIS' }, type: 'histogram', options: { column: 'pop_max' } } } ); var testClient = new TestClient(mapConfig, 1234); testClient.getLayergroup({ response: ERROR_RESPONSE }, function (err, layergroupResult) { assert.ok(!err, err); assert.strictEqual(layergroupResult.errors.length, 1); assert.strictEqual(layergroupResult.errors[0], 'Node with `source.id="ID-FOR-NONEXISTENT-ANALYSIS"`' + ' not found in analyses for dataview "pop_max_histogram"'); testClient.drain(done); }); }); it('camshaft: should return error missing analysis nodes for layers with some context', function (done) { var mapConfig = createMapConfig( [ { type: 'cartodb', options: { source: { id: 'HEAD' }, cartocss: '#polygons { polygon-fill: red; }', cartocss_version: '2.3.0' } } ], {}, [ { id: 'HEAD', type: 'buffer', params: { source: { id: 'HEAD', type: 'source', params: { query: 'select * from populated_places_simple_reduced' } }, radius: 50000 } } ] ); var testClient = new TestClient(mapConfig); // No apikey provided -> using default public apikey testClient.getLayergroup({ response: AUTH_ERROR_RESPONSE }, function (err, layergroupResult) { assert.ok(!err, err); assert.strictEqual(layergroupResult.errors.length, 1); assert.strictEqual( layergroupResult.errors[0], 'Analysis requires authentication with API key: permission denied.' ); assert.strictEqual(layergroupResult.errors_with_context[0].type, 'analysis'); assert.strictEqual( layergroupResult.errors_with_context[0].message, 'Analysis requires authentication with API key: permission denied.' ); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.id, 'HEAD'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.type, 'buffer'); testClient.drain(done); }); }); it('camshaft: should return error: Missing required param "radius"; with context', function (done) { var mapConfig = createMapConfig( [ { type: 'cartodb', options: { source: { id: 'HEAD' }, cartocss: '#polygons { polygon-fill: red; }', cartocss_version: '2.3.0' } } ], {}, [ { id: 'HEAD', type: 'buffer', params: { source: { id: 'HEAD2', type: 'source', params: { query: 'select * from populated_places_simple_reduced' } } } } ] ); var testClient = new TestClient(mapConfig, 1234); testClient.getLayergroup({ response: ERROR_RESPONSE }, function (err, layergroupResult) { assert.ok(!err, err); assert.strictEqual(layergroupResult.errors.length, 1); assert.strictEqual( layergroupResult.errors[0], 'Missing required param "radius"' ); assert.strictEqual(layergroupResult.errors_with_context[0].type, 'analysis'); assert.strictEqual(layergroupResult.errors_with_context[0].message, 'Missing required param "radius"'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.id, 'HEAD'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.type, 'buffer'); testClient.drain(done); }); }); it('should return missing param error of outer node indicating the node_id and context', function (done) { var mapConfig = createMapConfig([{ type: 'cartodb', options: { source: { id: 'HEAD' }, cartocss: '#polygons { polygon-fill: red; }', cartocss_version: '2.3.0' } }], {}, [{ id: 'HEAD', type: 'buffer', params: { source: { id: 'HEAD2', type: 'buffer', params: { source: { id: 'HEAD3', type: 'source', params: { query: 'select * from populated_places_simple_reduced' } }, radius: 10 } } } // radius: 'missing' }]); var testClient = new TestClient(mapConfig, 1234); testClient.getLayergroup({ response: ERROR_RESPONSE }, function (err, layergroupResult) { assert.ok(!err, err); assert.strictEqual(layergroupResult.errors.length, 1); assert.strictEqual( layergroupResult.errors[0], 'Missing required param "radius"' ); assert.strictEqual(layergroupResult.errors_with_context[0].type, 'analysis'); assert.strictEqual(layergroupResult.errors_with_context[0].message, 'Missing required param "radius"'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.id, 'HEAD'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.type, 'buffer'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.node_id, 'HEAD'); testClient.drain(done); }); }); it('should return invalid param type error of inner node indicating the node_id and context', function (done) { var mapConfig = createMapConfig([{ type: 'cartodb', options: { source: { id: 'HEAD' }, cartocss: '#polygons { polygon-fill: red; }', cartocss_version: '2.3.0' } }], {}, [{ id: 'HEAD', type: 'buffer', params: { source: { id: 'HEAD2', type: 'buffer', params: { source: { id: 'HEAD3', type: 'source', params: { query: 'select * from populated_places_simple_reduced' } }, radius: 'invalid_radius' } }, radius: 10 } }]); var testClient = new TestClient(mapConfig, 1234); testClient.getLayergroup({ response: ERROR_RESPONSE }, function (err, layergroupResult) { assert.ok(!err, err); assert.strictEqual(layergroupResult.errors.length, 1); assert.strictEqual( layergroupResult.errors[0], 'Invalid type for param "radius", expects "number" type, got `"invalid_radius"`' ); assert.strictEqual(layergroupResult.errors_with_context[0].type, 'analysis'); assert.strictEqual( layergroupResult.errors_with_context[0].message, 'Invalid type for param "radius", expects "number" type, got `"invalid_radius"`' ); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.id, 'HEAD'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.type, 'buffer'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.node_id, 'HEAD2'); testClient.drain(done); }); }); it('should return "function does not exist" indicating the node_id and context', function (done) { var mapConfig = createMapConfig([{ type: 'cartodb', options: { source: { id: 'HEAD' }, cartocss: '#polygons { polygon-fill: red; }', cartocss_version: '2.3.0' } }], {}, [{ id: 'HEAD', type: 'buffer', params: { source: { id: 'HEAD2', type: 'buffer', params: { source: { id: 'HEAD3', type: 'deprecated-sql-function', params: { id: 'HEAD4', function_name: 'DEP_EXT_does_not_exist_fn', primary_source: { type: 'source', params: { query: 'select * from populated_places_simple_reduced' } }, function_args: ['wadus'] } }, radius: 10 } }, radius: 10 } }]); var testClient = new TestClient(mapConfig, 1234); testClient.getLayergroup({ response: ERROR_RESPONSE }, function (err, layergroupResult) { assert.ok(!err, err); assert.strictEqual(layergroupResult.errors.length, 1); assert.strictEqual( layergroupResult.errors[0], 'function dep_ext_does_not_exist_fn(unknown, unknown, unknown, text[], unknown) does not exist' ); assert.strictEqual(layergroupResult.errors_with_context[0].type, 'analysis'); assert.strictEqual( layergroupResult.errors_with_context[0].message, 'function dep_ext_does_not_exist_fn(unknown, unknown, unknown, text[], unknown) does not exist' ); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.id, 'HEAD'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.type, 'buffer'); assert.strictEqual(layergroupResult.errors_with_context[0].analysis.node_id, 'HEAD3'); testClient.drain(done); }); }); });