Files
carto.js/test/spec/api/v4/source/sql.spec.js
2020-06-13 18:34:34 +08:00

258 lines
9.5 KiB
JavaScript

const Base = require('../../../../../src/api/v4/source/base');
const carto = require('../../../../../src/api/v4');
describe('api/v4/source/sql', function () {
var sqlQuery;
beforeEach(function () {
sqlQuery = new carto.source.SQL('SELECT * FROM ne_10m_populated_places_simple WHERE adm0name = \'Spain\'');
});
describe('constructor', function () {
it('should return a new Dataset object', function () {
expect(sqlQuery).toBeDefined();
});
it('should autogenerate an id', function () {
expect(sqlQuery.getId()).toMatch(/S\d+/);
});
it('should throw an error if query is not provided', function () {
expect(function () {
new carto.source.SQL(); // eslint-disable-line
}).toThrowError('SQL Source must have a SQL query.');
});
it('should throw an error if query is empty', function () {
expect(function () {
new carto.source.SQL(''); // eslint-disable-line
}).toThrowError('SQL Source must have a SQL query.');
});
it('should throw an error if query is not a valid string', function () {
expect(function () {
new carto.source.SQL(3333); // eslint-disable-line
}).toThrowError('SQL Query must be a string.');
});
});
describe('.setQuery', function () {
it('should set the query', function () {
sqlQuery.setQuery('SELECT foo FROM bar');
expect(sqlQuery.getQuery()).toEqual('SELECT foo FROM bar');
});
it('should throw an error if query is empty', function () {
expect(function () {
sqlQuery.setQuery('');
}).toThrowError('SQL Source must have a SQL query.');
});
it('should throw an error if query is not a valid string', function () {
expect(function () {
sqlQuery.setQuery(333);
}).toThrowError('SQL Query must be a string.');
});
it('should trigger an queryChanged event when there is no internal model', function (done) {
var expectedQuery = 'SELECT * FROM ne_10m_populated_places_simple LIMIT 10';
sqlQuery.on('queryChanged', function (newQuery) {
expect(newQuery).toEqual(expectedQuery);
done();
});
sqlQuery.setQuery(expectedQuery);
});
it('should trigger an queryChanged event when there is an internal model', function (done) {
var client = new carto.Client({
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
username: 'cartojs-test'
});
var style = new carto.style.CartoCSS('#layer { marker-fill: red; }');
var layer = new carto.layer.Layer(sqlQuery, style);
var queryChangedSpy = jasmine.createSpy('queryChangedSpy');
var newQuery = 'SELECT * FROM ne_10m_populated_places_simple LIMIT 10';
sqlQuery.on('queryChanged', queryChangedSpy);
client.addLayer(layer)
.then(function () {
return sqlQuery.setQuery(newQuery);
})
.then(function () {
expect(queryChangedSpy).toHaveBeenCalledWith(newQuery);
done();
});
});
it('should return a resolved promise when there is no internal model', function (done) {
var newQuery = 'SELECT * FROM ne_10m_populated_places_simple';
sqlQuery.setQuery(newQuery)
.then(function () {
expect(sqlQuery.getQuery()).toEqual(newQuery);
done();
});
});
it('should return a resolved promise when there is an internal model', function (done) {
var client = new carto.Client({
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
username: 'cartojs-test'
});
var style = new carto.style.CartoCSS('#layer { marker-fill: red; }');
var layer = new carto.layer.Layer(sqlQuery, style);
var newQuery = 'SELECT * FROM ne_10m_populated_places_simple LIMIT 10';
client.addLayer(layer)
.then(function () {
return sqlQuery.setQuery(newQuery);
})
.then(function () {
expect(sqlQuery.getQuery()).toEqual(newQuery);
done();
});
});
it('should return a rejected promise with a CartoError when there is an internal model (and a reload error)', function (done) {
var client = new carto.Client({
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
username: 'cartojs-test'
});
var style = new carto.style.CartoCSS('#layer { marker-fill: red; }');
var layer = new carto.layer.Layer(sqlQuery, style);
var newQuery = 'SELECT * FROM invalid_dataset';
client.addLayer(layer)
.then(function () {
return sqlQuery.setQuery(newQuery);
})
.catch(function (cartoError) {
expect(cartoError.message).toMatch(/Invalid dataset name used. Dataset "invalid_dataset" does not exist./);
done();
});
});
});
describe('$setEngine', function () {
it('should create an internal model with the dataset attrs and the engine', function () {
sqlQuery.$setEngine('fakeEngine');
var internalModel = sqlQuery.$getInternalModel();
expect(internalModel.get('id')).toEqual(sqlQuery.getId());
expect(internalModel.get('query')).toEqual('SELECT * FROM ne_10m_populated_places_simple WHERE adm0name = \'Spain\'');
expect(internalModel._engine).toEqual('fakeEngine');
});
});
describe('.getQueryToApply', function () {
let populatedPlacesSQL;
beforeEach(function () {
populatedPlacesSQL = new carto.source.SQL('SELECT * FROM ne_10m_populated_places_simple');
spyOn(populatedPlacesSQL, '_updateInternalModelQuery');
});
it('should return original query if applied filters returns no SQL', function () {
expect(populatedPlacesSQL._getQueryToApply()).toBe('SELECT * FROM ne_10m_populated_places_simple');
});
it('should return wrapped query if filters are applied', function () {
populatedPlacesSQL.addFilter(new carto.filter.Category('fake_column', { in: ['category'] }));
expect(populatedPlacesSQL._getQueryToApply()).toBe("SELECT * FROM (SELECT * FROM ne_10m_populated_places_simple) as originalQuery WHERE fake_column IN ('category')");
});
});
describe('.addFilter', function () {
let populatedPlacesSQL;
beforeEach(function () {
spyOn(Base.prototype, 'addFilter');
populatedPlacesSQL = new carto.source.SQL('SELECT * FROM ne_10m_populated_places_simple');
spyOn(populatedPlacesSQL, '_updateInternalModelQuery');
});
it('should call original addFilter and _updateInternalModelQuery', function () {
populatedPlacesSQL.addFilter(new carto.filter.Category('fake_column', { in: ['category'] }));
expect(Base.prototype.addFilter).toHaveBeenCalled();
expect(populatedPlacesSQL._updateInternalModelQuery).toHaveBeenCalledWith(populatedPlacesSQL._getQueryToApply());
});
});
describe('.removeFilter', function () {
let populatedPlacesDataset, filter;
beforeEach(function () {
spyOn(Base.prototype, 'addFilter');
populatedPlacesDataset = new carto.source.Dataset('ne_10m_populated_places_simple');
spyOn(populatedPlacesDataset, '_updateInternalModelQuery');
filter = populatedPlacesDataset.addFilter(new carto.filter.Category('fake_column', { in: ['category'] }));
populatedPlacesDataset.addFilter(filter);
});
it('should call original removeFilter and _updateInternalModelQuery', function () {
populatedPlacesDataset.removeFilter(filter);
expect(Base.prototype.addFilter).toHaveBeenCalled();
expect(populatedPlacesDataset._updateInternalModelQuery).toHaveBeenCalledWith(populatedPlacesDataset._getQueryToApply());
});
});
describe('.getFilters', function () {
let populatedPlacesDataset, filter;
beforeEach(function () {
filter = new carto.filter.Category('fake_column', { in: ['category'] });
populatedPlacesDataset = new carto.source.Dataset('ne_10m_populated_places_simple');
populatedPlacesDataset.addFilter(filter);
});
it('should return added filters', function () {
expect(populatedPlacesDataset.getFilters()).toEqual([filter]);
});
});
describe('errors', function () {
it('should trigger an error when invalid', function (done) {
var client = new carto.Client({
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
username: 'cartojs-test'
});
// The following sql has the invalid operator: ===
var invalidSource = new carto.source.SQL('SELECT * FROM ne_10m_populated_places_simple WHERE adm0name === \'Spain\'');
var cartoCss = new carto.style.CartoCSS('#layer { marker-fill: red; }');
invalidSource.on('error', function (cartoError) {
expect(cartoError.message).toMatch(/operator does not exist/);
done();
});
var layer = new carto.layer.Layer(invalidSource, cartoCss);
client.addLayer(layer).catch(function () { }); // Prevent console "uncaught error" warning.
});
it('should trigger a CartoError when there is an error in the internal model', function () {
var client = new carto.Client({
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
username: 'cartojs-test'
});
var source = new carto.source.SQL('SELECT * FROM ne_10m_populated_places_simple');
var cartoCss = new carto.style.CartoCSS('#layer { marker-fill: red; }');
var layer = new carto.layer.Layer(source, cartoCss);
var spy = jasmine.createSpy('spy');
source.on(carto.events.ERROR, spy);
client.addLayer(layer);
source._internalModel.set('error', 'an error');
expect(spy).toHaveBeenCalledWith(jasmine.objectContaining({
name: 'CartoError',
originalError: 'an error'
}));
});
});
});