cartodb-4.42/lib/assets/javascripts/cdb/test/spec/api/sql.spec.js
2024-04-06 05:25:13 +00:00

430 lines
16 KiB
JavaScript

describe('SQL api client', function() {
var USER = 'rambo';
var TEST_DATA = { test: 'good' };
var sql;
var ajaxParams;
var throwError = false;
var jquery_ajax;
var ajax;
beforeEach(function() {
ajaxParams = null;
ajax = function(params) {
ajaxParams = params;
_.defer(function() {
if(!throwError && params.success) params.success(TEST_DATA, 200);
throwError && params.error && params.error({
responseText: JSON.stringify({
error: ['jaja']
})
});
});
}
sql = new cartodb.SQL({
user: USER,
protocol: 'https',
ajax: ajax
})
jquery_ajax = $.ajax;
});
afterEach(function() {
$.ajax = jquery_ajax;
});
it("should compile the url if not completeDomain passed", function() {
expect(sql._host()).toEqual('https://rambo.carto.com/api/v2/sql');
});
it("should compile the url if completeDomain passed", function() {
var sqlBis = new cartodb.SQL({
user: USER,
protocol: 'https',
completeDomain: 'http://troloroloro.com'
})
expect(sqlBis._host()).toEqual('http://troloroloro.com/api/v2/sql');
});
it("should execute a query", function() {
sql.execute('select * from table');
expect(ajaxParams.url).toEqual(
'https://' + USER + '.carto.com/api/v2/sql?q=' + encodeURIComponent('select * from table')
)
expect(ajaxParams.type).toEqual('get');
expect(ajaxParams.dataType).toEqual('json');
expect(ajaxParams.crossDomain).toEqual(true);
});
it("should parse template", function() {
sql.execute('select * from {{table}}', {
table: 'rambo'
})
expect(ajaxParams.url).toEqual(
'https://' + USER + '.carto.com/api/v2/sql?q=' + encodeURIComponent('select * from rambo')
)
});
it("should execute a long query", function() {
//Generating a giant query
var long_sql = []
var i = 2000;
while (--i) long_sql.push("10000");
var long_query = 'SELECT * ' + long_sql;
sql.execute(long_query);
expect(ajaxParams.url).toEqual(
'https://' + USER + '.carto.com/api/v2/sql'
)
expect(ajaxParams.data.q).toEqual(long_query);
expect(ajaxParams.type).toEqual('post');
expect(ajaxParams.dataType).toEqual('json');
expect(ajaxParams.crossDomain).toEqual(true);
});
it("should execute a long query with params", function() {
s = new cartodb.SQL({
user: 'rambo',
format: 'geojson',
protocol: 'http',
host: 'charlies.com',
api_key: 'testkey',
rambo: 'test',
ajax: ajax
})
//Generating a giant query
var long_sql = []
var i = 2000;
while (--i) long_sql.push("10000");
var long_query = 'SELECT * ' + long_sql;
s.execute(long_query, null, {
dp: 2
})
expect(ajaxParams.url.indexOf('http://')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('rambo.charlies.com')).not.toEqual(-1);
//Check that we don't have params in the URI
expect(ajaxParams.url.indexOf('&format=geojson')).toEqual(-1);
expect(ajaxParams.url.indexOf('&api_key=testkey')).toEqual(-1);
expect(ajaxParams.url.indexOf('&dp=2')).toEqual(-1);
expect(ajaxParams.url.indexOf('&rambo')).toEqual(-1);
//Check that we have the params in the body
expect(ajaxParams.data.q).toEqual(long_query);
expect(ajaxParams.data.format).toEqual('geojson');
expect(ajaxParams.data.api_key).toEqual('testkey');
expect(ajaxParams.data.dp).toEqual(2);
expect(ajaxParams.rambo).toEqual('test');
});
it("should substitute mapnik tokens", function() {
sql.execute('select !pixel_width! as w, !pixel_height! as h, !bbox! as b from {{table}}', {
table: 't'
})
var earth_circumference = 40075017;
var tile_size = 256;
var srid = 3857;
var full_resolution = earth_circumference/tile_size;
var shift = earth_circumference / 2.0;
var pw = full_resolution;
var ph = pw;
var bbox = 'ST_MakeEnvelope(' + (-shift) + ',' + (-shift) + ','
+ shift + ',' + shift + ',' + srid + ')';
expect(ajaxParams.url).toEqual(
'https://' + USER + '.carto.com/api/v2/sql?q=' + encodeURIComponent(
'select ' + pw + ' as w, ' + ph + ' as h, '
+ bbox + ' as b from t')
)
});
it("should call promise", function(done) {
var data;
var data_callback;
sql.execute('select * from bla', function(data) { data_callback = data }).done(function(d) {
data = d;
});
setTimeout(function() {
expect(data).toEqual(TEST_DATA);
expect(data_callback).toEqual(TEST_DATA);
done()
}, 500); //Fix cartodb.js issue #336
});
it("should call promise on error", function(done) {
throwError = true;
var err = false;
sql.execute('select * from bla').error(function(d) {
err = true;
});
setTimeout(function() {
expect(err).toEqual(true);
done();
},10);
});
it("should include url params", function() {
s = new cartodb.SQL({
user: 'rambo',
format: 'geojson',
protocol: 'http',
host: 'charlies.com',
api_key: 'testkey',
rambo: 'test',
ajax: ajax
})
s.execute('select * from rambo', null, {
dp: 2
})
expect(ajaxParams.url.indexOf('http://')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('rambo.charlies.com')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('&format=geojson')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('&api_key=testkey')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('&dp=2')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('&rambo')).toEqual(-1);
});
it("should include extra url params", function() {
s = new cartodb.SQL({
user: 'rambo',
format: 'geojson',
protocol: 'http',
host: 'charlies.com',
api_key: 'testkey',
rambo: 'test',
ajax: ajax,
extra_params: ['rambo']
})
s.execute('select * from rambo', null, {
dp: 2
})
expect(ajaxParams.url.indexOf('http://')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('rambo.charlies.com')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('&format=geojson')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('&api_key=testkey')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('&dp=2')).not.toEqual(-1);
expect(ajaxParams.url.indexOf('&rambo=test')).not.toEqual(-1);
s.execute('select * from rambo', null, {
dp: 2,
rambo: 'test2'
})
expect(ajaxParams.url.indexOf('&rambo=test2')).not.toEqual(-1);
});
it("should use jsonp if browser does not support cors", function() {
$.support.cors = false;
s = new cartodb.SQL({ user: 'jaja', ajax: ajax });
expect(s.options.jsonp).toEqual(true);
s.execute('select * from rambo', null, {
dp: 2,
jsonpCallback: 'test_callback',
cache: false
})
expect(ajaxParams.dataType).toEqual('jsonp');
expect(ajaxParams.crossDomain).toEqual(undefined);
expect(ajaxParams.jsonp).toEqual(undefined);
expect(ajaxParams.jsonpCallback).toEqual('test_callback');
expect(ajaxParams.cache).toEqual(false);
$.support.cors = true;
});
it("should get bounds for query", function() {
var sql = 'SELECT ST_XMin(ST_Extent(the_geom)) as minx,' +
' ST_YMin(ST_Extent(the_geom)) as miny,'+
' ST_XMax(ST_Extent(the_geom)) as maxx,' +
' ST_YMax(ST_Extent(the_geom)) as maxy' +
' from (select * from rambo where id=2) as subq';
s = new cartodb.SQL({ user: 'jaja', ajax: ajax });
s.getBounds('select * from rambo where id={{id}}', {id: 2});
expect(ajaxParams.url.indexOf(encodeURIComponent(sql))).not.toEqual(-1);
});
it("should get bounds for query with appostrophes", function() {
s = new cartodb.SQL({ user: 'jaja', ajax: ajax });
s.getBounds("select * from country where name={{ name }}", { name: "'Spain'"});
expect(ajaxParams.url.indexOf("%26amp%3B%2339%3B")).toEqual(-1);
});
});
describe('sql.table', function() {
var USER = 'rambo';
var sql;
beforeEach(function() {
ajaxParams = null;
sql = new cartodb.SQL({
user: USER,
protocol: 'https'
})
});
it("sql", function() {
var s = sql.table('test');
expect(s.sql()).toEqual('select * from test');
s.columns(['age', 'jeta'])
expect(s.sql()).toEqual('select age,jeta from test');
s.filter('age < 10')
expect(s.sql()).toEqual('select age,jeta from test where age < 10');
s.limit(15)
expect(s.sql()).toEqual('select age,jeta from test where age < 10 limit 15');
s.order_by('age')
expect(s.sql()).toEqual('select age,jeta from test where age < 10 limit 15 order by age');
})
});
describe("column descriptions", function(){
var USER = 'manolo';
var sql;
beforeAll(function(){
this.colDate = new Backbone.Model(JSON.parse('{"name":"object_postedtime","type":"date","geometry_type":"point","bbox":[[-28.92163128242129,-201.09375],[75.84516854027044,196.875]],"analyzed":true,"success":true,"stats":{"type":"date","start_time":"2015-02-19T15:13:16.000Z","end_time":"2015-02-22T04:34:05.000Z","range":220849000,"steps":1024,"null_ratio":0,"column":"object_postedtime"}}'));
this.colFloat = new Backbone.Model(JSON.parse('{"name":"asdfd","type":"number","geometry_type":"point"}'));
this.colString = new Backbone.Model(JSON.parse('{"name":"asdfd","type":"string","geometry_type":"point"}'));
this.colGeom = new Backbone.Model(JSON.parse('{"name":"asdfd","type":"geometry","geometry_type":"point"}'));
this.colBoolean = new Backbone.Model(JSON.parse('{"name":"asdfd","type":"boolean","geometry_type":"point"}'));
this.query = "SELECT * FROM whatevs";
sql = new cartodb.SQL({
user: USER,
protocol: 'https'
});
sql.execute = function(sql, callback){
callback({});
}
});
it("should deduct correct describe method", function(){
spyOn(sql, "describeDate");
sql.describe(this.query, this.colDate, {type: this.colDate.get("type")}, function(){});
expect(sql.describeDate).toHaveBeenCalled;
spyOn(sql, "describeFloat");
sql.describe(this.query, this.colFloat, {type: this.colFloat.get("type")}, function(){});
expect(sql.describeFloat).toHaveBeenCalled();
spyOn(sql, "describeString");
sql.describe(this.query, this.colString, {type: this.colString.get("type")}, function(){});
expect(sql.describeString).toHaveBeenCalled();
spyOn(sql, "describeGeom");
sql.describe(this.query, this.colGeom, {type: this.colGeom.get("type")}, function(){});
expect(sql.describeGeom).toHaveBeenCalled();
spyOn(sql, "describeBoolean");
sql.describe(this.query, this.colBoolean, {type: this.colBoolean.get("type")}, function(){});
expect(sql.describeBoolean).toHaveBeenCalled();
});
describe("string describer", function(){
var description;
beforeAll(function(done){
sql.execute = function(sql, callback){
var data = JSON.parse('{"rows":[{"uniq":462,"cnt":487,"null_count":1,"null_ratio":0.002053388090349076,"skew":0.043121149897330596,"array_agg":""}],"time":0.01,"fields":{"uniq":{"type":"number"},"cnt":{"type":"number"},"null_count":{"type":"number"},"null_ratio":{"type":"number"},"skew":{"type":"number"},"array_agg":{"type":"unknown(2287)"}},"total_rows":1}');
callback(data);
}
var callback = function(stuff){
description = stuff;
done();
}
sql.describeString(sql, this.colString, callback); // THE COLS DON'T MATCH!!!
});
it("should return correct properties", function(){
expect(description.hist.constructor).toEqual(Array); // Right now it's an empty array because JSON.parse doesn't like our way of notating histograms
expect(description.type).toEqual("string");
expect(typeof description.null_count).toEqual("number");
expect(typeof description.distinct).toEqual("number");
expect(typeof description.null_ratio).toEqual("number");
expect(typeof description.skew).toEqual("number");
expect(typeof description.weight).toEqual("number");
});
});
describe("geometry describer", function(){
var description;
beforeAll(function(done){
sql.execute = function(sql, callback){
var data = {"rows":[{"bbox": '{"type":"Polygon","coordinates":[[[-179.9284,-65.2446],[-179.9284,81.8962],[179.9698,81.8962],[179.9698,-65.2446],[-179.9284,-65.2446]]]}',"geometry_type":"ST_Point","clusterrate":0.20359746623640493,"density":0.105333307745705}],"time":0.035,"fields":{"bbox":{"type":"string"},"geometry_type":{"type":"string"},"clusterrate":{"type":"number"},"density":{"type":"number"}},"total_rows":1};
callback(data);
}
var callback = function(stuff){
description = stuff;
done();
}
sql.describeGeom(sql, this.colGeom, callback);
});
it("should return correct properties", function(){
expect(description.type).toEqual("geom");
expect(["ST_Point", "ST_Line", "ST_Polygon"].indexOf(description.geometry_type) > -1).toBe(true);
expect(description.bbox.constructor).toEqual(Array);
expect(typeof description.density).toEqual("number");
expect(typeof description.cluster_rate).toEqual("number");
})
});
describe("number describer", function(){
var description;
beforeAll(function(done){
sql.execute = function(sql, callback){
var data = JSON.parse('{"rows":[{"hist":"{\\"(1,empty,69368)\\",\\"(25,empty,11063)\\"}","min":0,"max":4,"avg":0.3745819397993311,"cnt":89401,"uniq":5,"null_ratio":0,"stddev":0.000009057366328792043,"stddevmean":2.1617223091836313,"dist_type":"U","quantiles":[0,1,2,2,3,4,4],"equalint":[0,0,0,0,0,0,0],"jenks":[0,1,2,3,4],"headtails":[0,1,2,3,4],"cat_hist":"{\\"(1,empty,69368)\\",\\"(25,empty,11063)\\"}"}],"time":1.442,"fields":{"hist":{"type":"unknown(2287)"},"min":{"type":"number"},"max":{"type":"number"},"avg":{"type":"number"},"cnt":{"type":"number"},"uniq":{"type":"number"},"null_ratio":{"type":"number"},"stddev":{"type":"number"},"stddevmean":{"type":"number"},"dist_type":{"type":"string"},"quantiles":{"type":"number[]"},"equalint":{"type":"number[]"},"jenks":{"type":"number[]"},"headtails":{"type":"number[]"},"cat_hist":{"type":"unknown(2287)"}},"total_rows":1}');
callback(data);
}
var callback = function(stuff){
description = stuff;
done();
}
sql.describeFloat(sql, this.colGeom, callback);
});
it("should return correct properties", function(){
expect(description.type).toEqual("number");
expect(["A", "U", "F", "J"].indexOf(description.dist_type) > -1).toBe(true);
var numTypes = ["avg", "max", "min", "stddevmean", "weight", "stddev", "null_ratio", "count"];
for(var i = 0; i < numTypes.length; i++){
expect(typeof description[numTypes[i]]).toEqual("number");
}
var arrayTypes = ["quantiles", "equalint", "jenks", "headtails", "cat_hist", "hist"];
for(var i = 0; i < arrayTypes.length; i++){
expect(description[arrayTypes[i]].constructor).toEqual(Array);
}
})
});
describe("boolean describer", function(){
var description;
beforeAll(function(done){
sql.execute = function(sql, callback){
var data = {"rows":[
{"true_ratio":0.3377926421404682,"null_ratio":0,"uniq":2,"cnt":89401}
],
"time":0.251,
"fields":{"true_ratio":{"type":"number"},"null_ratio":{"type":"number"},"uniq":{"type":"number"},"cnt":{"type":"number"}},
"total_rows":1
};
callback(data);
}
var callback = function(stuff){
description = stuff;
done();
}
sql.describeBoolean(sql, this.colGeom, callback);
});
it("should return correct properties", function(){
expect(description.type).toEqual("boolean");
expect(typeof description.true_ratio).toEqual("number");
expect(typeof description.distinct).toEqual("number");
expect(typeof description.count).toEqual("number");
expect(typeof description.null_ratio).toEqual("number");
})
});
});