Initial commit
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
var Aggregation = require('../../../../../src/api/v4/layer/aggregation');
|
||||
|
||||
describe('layer-aggregation', function () {
|
||||
var options;
|
||||
beforeEach(function () {
|
||||
options = {
|
||||
threshold: 10000,
|
||||
resolution: 1,
|
||||
placement: 'point-sample',
|
||||
columns: {
|
||||
fake_name_0: {
|
||||
aggregateFunction: 'sum',
|
||||
aggregatedColumn: 'fake_column_0'
|
||||
},
|
||||
fake_name_1: {
|
||||
aggregateFunction: 'avg',
|
||||
aggregatedColumn: 'fake_column_1'
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
describe('constructor', function () {
|
||||
it('should return a simple object when the parameters are valid', function () {
|
||||
var aggregation = new Aggregation(options);
|
||||
|
||||
// Multiple specs for easy debugging
|
||||
expect(aggregation.threshold).toEqual(options.threshold);
|
||||
expect(aggregation.resolution).toEqual(options.resolution);
|
||||
expect(aggregation.placement).toEqual(options.placement);
|
||||
expect(aggregation.columns.fake_name_0).toEqual({
|
||||
aggregate_function: 'sum',
|
||||
aggregated_column: 'fake_column_0'
|
||||
});
|
||||
expect(aggregation.columns.fake_name_1).toEqual({
|
||||
aggregate_function: 'avg',
|
||||
aggregated_column: 'fake_column_1'
|
||||
});
|
||||
});
|
||||
|
||||
describe('errors', function () {
|
||||
describe('threshold', function () {
|
||||
it('should throw an error when threshold is not defined', function () {
|
||||
delete options.threshold;
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError('Aggregation threshold is required.');
|
||||
});
|
||||
|
||||
it('should throw an error when threshold is not a positive integer', function () {
|
||||
options.threshold = 0;
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError('Aggregation threshold must be an integer value greater than 0.');
|
||||
|
||||
options.threshold = -1;
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError('Aggregation threshold must be an integer value greater than 0.');
|
||||
|
||||
options.threshold = 2.5;
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError('Aggregation threshold must be an integer value greater than 0.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolution', function () {
|
||||
it('should throw an error when resolution is not defined', function () {
|
||||
options.resolution = undefined;
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError('Aggregation resolution is required.');
|
||||
});
|
||||
|
||||
it('should throw an error when resolution is not an integer between 1 and 16', function () {
|
||||
var expectedErrorMessage = 'Aggregation resolution must be 0.5, 1 or powers of 2 up to 256 (2, 4, 8, 16, 32, 64, 128, 256).';
|
||||
options.resolution = 0;
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError(expectedErrorMessage);
|
||||
|
||||
options.resolution = 17;
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError(expectedErrorMessage);
|
||||
|
||||
var validOnes = [0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256];
|
||||
validOnes.forEach(function (resolution) {
|
||||
expect(function () {
|
||||
options.resolution = resolution;
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).not.toThrowError();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('placement', function () {
|
||||
it('should throw an error when placement is not one of our three valid placements', function () {
|
||||
options.placement = 'invalid_placement';
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError('Aggregation placement is not valid. Must be one of these values: `point-sample`, `point-grid`, `centroid`');
|
||||
});
|
||||
});
|
||||
|
||||
describe('columns', function () {
|
||||
it('should thrown an error when column.aggregateFunction is not defined', function () {
|
||||
options.columns = {
|
||||
fake_name_0: {
|
||||
aggregatedColumn: 'fake_column_0'
|
||||
}
|
||||
};
|
||||
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError("Aggregation function for column 'fake_name_0' is required.");
|
||||
});
|
||||
|
||||
it('should thrown an error when column.aggregateFunction is not a valid function', function () {
|
||||
options.columns = {
|
||||
fake_name_0: {
|
||||
aggregatedColumn: 'fake_column_0',
|
||||
aggregateFunction: 'invalid_function'
|
||||
}
|
||||
};
|
||||
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError("Aggregation function for column 'fake_name_0' is not valid. Use carto.aggregation.function");
|
||||
});
|
||||
|
||||
it('should thrown an error when column.aggregatedColumn is not defined', function () {
|
||||
options.columns = {
|
||||
fake_name_0: {
|
||||
aggregateFunction: 'sum'
|
||||
}
|
||||
};
|
||||
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError("Column to be aggregated to 'fake_name_0' is required.");
|
||||
});
|
||||
|
||||
it('should thrown an error when column.aggregatedColumn is not a string', function () {
|
||||
options.columns = {
|
||||
fake_name_0: {
|
||||
aggregatedColumn: 4500,
|
||||
aggregateFunction: 'sum'
|
||||
}
|
||||
};
|
||||
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).toThrowError("Column to be aggregated to 'fake_name_0' must be a string.");
|
||||
});
|
||||
});
|
||||
|
||||
describe('optional placement and columns', function () {
|
||||
it('should now throw an error when neither placement nor columns appear', function () {
|
||||
delete options.columns;
|
||||
delete options.placement;
|
||||
|
||||
expect(function () {
|
||||
new Aggregation(options); // eslint-disable-line
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,677 @@
|
||||
var carto = require('../../../../../src/api/v4');
|
||||
|
||||
describe('api/v4/layer', function () {
|
||||
var source;
|
||||
var style;
|
||||
var originalTimeout;
|
||||
|
||||
beforeEach(function () {
|
||||
source = new carto.source.Dataset('ne_10m_populated_places_simple');
|
||||
style = new carto.style.CartoCSS('#layer { marker-fill: red; }');
|
||||
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
|
||||
});
|
||||
|
||||
describe('constructor', function () {
|
||||
it('should build a new Layer params: (source, style)', function () {
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
|
||||
expect(layer.getSource()).toEqual(source);
|
||||
expect(layer.getStyle()).toEqual(style);
|
||||
});
|
||||
|
||||
it('should assign a unique layer ID string', function () {
|
||||
var layer1 = new carto.layer.Layer(source, style);
|
||||
var layer2 = new carto.layer.Layer(source, style);
|
||||
|
||||
var id1 = layer1.getId();
|
||||
var id2 = layer2.getId();
|
||||
|
||||
expect(id1).toMatch(/L\d+/);
|
||||
expect(id2).toMatch(/L\d+/);
|
||||
expect(id1).not.toEqual(id2);
|
||||
});
|
||||
|
||||
it('should be able to create a hidden layer', function () {
|
||||
var layer = new carto.layer.Layer(source, style, {
|
||||
visible: false
|
||||
});
|
||||
|
||||
expect(layer.isHidden()).toBe(true);
|
||||
});
|
||||
|
||||
it('should build a new Layer params: (source, style, options)', function () {
|
||||
var layer = new carto.layer.Layer(source, style, {
|
||||
featureClickColumns: ['a', 'b'],
|
||||
featureOverColumns: ['c', 'd']
|
||||
});
|
||||
|
||||
expect(layer.getSource()).toEqual(source);
|
||||
expect(layer.getStyle()).toEqual(style);
|
||||
expect(layer.getFeatureClickColumns()).toEqual(['a', 'b']);
|
||||
expect(layer.getFeatureOverColumns()).toEqual(['c', 'd']);
|
||||
});
|
||||
|
||||
it('should throw an error if source is not valid', function () {
|
||||
expect(function () {
|
||||
new carto.layer.Layer({}, style); // eslint-disable-line
|
||||
}).toThrowError('The given object is not a valid source. See "carto.source.Base".');
|
||||
});
|
||||
|
||||
it('should throw an error if style is not valid', function () {
|
||||
expect(function () {
|
||||
new carto.layer.Layer(source, {}); // eslint-disable-line
|
||||
}).toThrowError('The given object is not a valid style. See "carto.style.Base".');
|
||||
});
|
||||
|
||||
it('should allow custom layer id as an option', function () {
|
||||
var layer = new carto.layer.Layer(source, style, { id: 'fake_id' });
|
||||
expect(layer.getId()).toEqual('fake_id');
|
||||
});
|
||||
|
||||
describe('columns validation', function () {
|
||||
var aggregation = new carto.layer.Aggregation({
|
||||
threshold: 1,
|
||||
resolution: 4,
|
||||
columns: {
|
||||
population: {
|
||||
aggregateFunction: 'sum',
|
||||
aggregatedColumn: 'pop_max'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should validate that featureClick columns are contained in aggregation columns', function () {
|
||||
expect(function () {
|
||||
new carto.layer.Layer(source, style, { // eslint-disable-line
|
||||
featureClickColumns: ['a', 'b'],
|
||||
aggregation: aggregation
|
||||
});
|
||||
}).toThrowError('Columns [a, b] set on `featureClick` do not match the columns set in aggregation options.');
|
||||
});
|
||||
|
||||
it('should validate that featureOver columns are contained in aggregation columns', function () {
|
||||
expect(function () {
|
||||
new carto.layer.Layer(source, style, { // eslint-disable-line
|
||||
featureOverColumns: ['a', 'b'],
|
||||
aggregation: aggregation
|
||||
});
|
||||
}).toThrowError('Columns [a, b] set on `featureOver` do not match the columns set in aggregation options.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.setStyle', function () {
|
||||
var layer;
|
||||
var newStyle;
|
||||
beforeEach(function () {
|
||||
layer = new carto.layer.Layer(source, style);
|
||||
newStyle = new carto.style.CartoCSS('#layer { marker-fill: green; }');
|
||||
});
|
||||
|
||||
it('should throw an error when the parameter is not a valid style', function () {
|
||||
expect(function () {
|
||||
layer.setStyle('bad-style');
|
||||
}).toThrowError('The given object is not a valid style. See "carto.style.Base".');
|
||||
});
|
||||
|
||||
describe('when the layer has no engine', function () {
|
||||
it('should set the layer style', function () {
|
||||
layer.setStyle(newStyle);
|
||||
|
||||
expect(layer.getStyle()).toEqual(newStyle);
|
||||
});
|
||||
|
||||
it('should fire a styleChanged event', function (done) {
|
||||
layer.on('styleChanged', function (l) {
|
||||
expect(l).toBe(layer);
|
||||
expect(l.getStyle()).toEqual(newStyle);
|
||||
done();
|
||||
});
|
||||
|
||||
layer.setStyle(newStyle);
|
||||
});
|
||||
|
||||
it('should not fire a styleChanged event when setting the same style twice', function () {
|
||||
var styleChangedSpy = jasmine.createSpy('styleChangedSpy');
|
||||
layer.on('styleChanged', styleChangedSpy);
|
||||
|
||||
layer.setStyle(style);
|
||||
|
||||
expect(styleChangedSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the layer has an engine', function () {
|
||||
var client;
|
||||
beforeEach(function () {
|
||||
client = new carto.Client({
|
||||
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
|
||||
username: 'cartojs-test'
|
||||
});
|
||||
});
|
||||
|
||||
describe('and the style has no engine', function () {
|
||||
it('should set the engine into the style and update the internal style.', function (done) {
|
||||
client.addLayer(layer)
|
||||
.then(function () {
|
||||
return layer.setStyle(newStyle);
|
||||
})
|
||||
.then(function () {
|
||||
expect(layer.getStyle().$getEngine()).toBe(layer._engine);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and the style has an engine', function () {
|
||||
it('should update the internal style when the engines are equal', function (done) {
|
||||
newStyle.$setEngine(client._engine);
|
||||
client.addLayer(layer)
|
||||
.then(function () {
|
||||
return layer.setStyle(newStyle);
|
||||
})
|
||||
.then(function () {
|
||||
expect(layer.getStyle().$getEngine()).toBe(layer._engine);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error when the engines are not equal', function (done) {
|
||||
newStyle.$setEngine('fakeEngine');
|
||||
client.addLayer(layer)
|
||||
.then(function () {
|
||||
expect(function () {
|
||||
return layer.setStyle(newStyle);
|
||||
}).toThrowError('A layer can\'t have a style which belongs to a different client.');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fire a cartoError when the style is invalid', function (done) {
|
||||
var styleChangedSpy = jasmine.createSpy('styleChangedSpy');
|
||||
layer.on('error', styleChangedSpy);
|
||||
client.addLayer(layer)
|
||||
.then(function () {
|
||||
var malformedStyle = new carto.style.CartoCSS('#layer { invalid-rule: foo}');
|
||||
return layer.setStyle(malformedStyle);
|
||||
})
|
||||
.catch(function () {
|
||||
expect(styleChangedSpy).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fire a styleChanged event when the layer belongs to a client', function (done) {
|
||||
var styleChangedSpy = jasmine.createSpy('styleChangedSpy');
|
||||
layer.on('styleChanged', styleChangedSpy);
|
||||
|
||||
client.addLayer(layer)
|
||||
.then(function () {
|
||||
return layer.setStyle(newStyle);
|
||||
})
|
||||
.then(function () {
|
||||
expect(styleChangedSpy).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should set the internal model style', function (done) {
|
||||
var client = new carto.Client({
|
||||
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
|
||||
username: 'cartojs-test'
|
||||
});
|
||||
|
||||
client.on(carto.events.ERROR, alert);
|
||||
client.addLayer(layer)
|
||||
.then(function () {
|
||||
client.on(carto.events.SUCCESS, function () {
|
||||
var expected = '#layer { marker-fill: green; }';
|
||||
var actual = layer.$getInternalModel().get('cartocss');
|
||||
expect(expected).toEqual(actual);
|
||||
done();
|
||||
});
|
||||
layer.setStyle(newStyle);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.$setEngine', function () {
|
||||
it('probando', function () {
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
var engineMock = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload').and.returnValue(Promise.resolve()) };
|
||||
var error = {
|
||||
message: 'an error'
|
||||
};
|
||||
var capturedError;
|
||||
layer.$setEngine(engineMock);
|
||||
layer.on(carto.events.ERROR, function (error) {
|
||||
capturedError = error;
|
||||
});
|
||||
|
||||
layer._internalModel.set('error', error);
|
||||
|
||||
expect(capturedError).toBeDefined();
|
||||
expect(capturedError.name).toEqual('CartoError');
|
||||
expect(capturedError.message).toEqual('an error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.setSource', function () {
|
||||
var layer;
|
||||
var newSource;
|
||||
|
||||
beforeEach(function () {
|
||||
layer = new carto.layer.Layer(source, style);
|
||||
newSource = new carto.source.SQL('SELECT * FROM ne_10m_populated_places_simple LIMIT 10');
|
||||
});
|
||||
|
||||
it('should throw an error when the source is not a valid parameter', function () {
|
||||
expect(function () {
|
||||
layer.setSource('bad-parameter');
|
||||
}).toThrowError('The given object is not a valid source. See "carto.source.Base".');
|
||||
});
|
||||
|
||||
describe('when the layer hasn\'t been set an engine', function () {
|
||||
it('should normally add the source', function () {
|
||||
layer.setSource(newSource);
|
||||
|
||||
expect(layer.getSource()).toEqual(newSource);
|
||||
});
|
||||
|
||||
it('should fire a sourceChanged event', function (done) {
|
||||
layer.on('sourceChanged', function (l) {
|
||||
expect(l).toBe(layer);
|
||||
expect(l.getSource()).toEqual(newSource);
|
||||
done();
|
||||
});
|
||||
|
||||
layer.setSource(newSource);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the layer has been set an engine', function () {
|
||||
var engineMock;
|
||||
beforeEach(function () {
|
||||
engineMock = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload').and.returnValue(Promise.resolve()) };
|
||||
layer.$setEngine(engineMock);
|
||||
});
|
||||
|
||||
describe('and the source has no engine', function () {
|
||||
it('should normally add the source', function (done) {
|
||||
layer.setSource(newSource)
|
||||
.then(function () {
|
||||
var actualSource = layer.$getInternalModel().get('source');
|
||||
var expectedSource = newSource.$getInternalModel();
|
||||
expect(actualSource).toBeDefined();
|
||||
expect(actualSource).toEqual(expectedSource);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fire a sourceChanged event', function (done) {
|
||||
var sourceChangedSpy = jasmine.createSpy('sourceChangedSpy');
|
||||
layer.on('sourceChanged', sourceChangedSpy);
|
||||
|
||||
layer.setSource(newSource)
|
||||
.then(function () {
|
||||
expect(sourceChangedSpy).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and the source has an engine', function () {
|
||||
it('should add the source if the engines are the same', function () {
|
||||
newSource.$setEngine(engineMock);
|
||||
|
||||
layer.setSource(newSource);
|
||||
|
||||
var actualSource = layer.$getInternalModel().get('source');
|
||||
var expectedSource = newSource.$getInternalModel();
|
||||
expect(actualSource).toEqual(expectedSource);
|
||||
});
|
||||
|
||||
it('should throw an error if the engines are different', function () {
|
||||
// This engine is different from the layer's one.
|
||||
var engineMock1 = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload') };
|
||||
newSource.$setEngine(engineMock1);
|
||||
|
||||
expect(function () {
|
||||
layer.setSource(newSource);
|
||||
}).toThrowError('A layer can\'t have a source which belongs to a different client.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not fire a sourceChanged event when setting the same source twice', function () {
|
||||
var sourceChangedSpy = jasmine.createSpy('sourceChangedSpy');
|
||||
layer.on('sourceChanged', sourceChangedSpy);
|
||||
|
||||
layer.setSource(source);
|
||||
|
||||
expect(sourceChangedSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fire a cartoError when the source is invalid', function (done) {
|
||||
var client = new carto.Client({
|
||||
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
|
||||
username: 'cartojs-test'
|
||||
});
|
||||
var sourceChangedSoy = jasmine.createSpy('sourceChangedSoy');
|
||||
layer.on('error', sourceChangedSoy);
|
||||
client.addLayer(layer)
|
||||
.then(function () {
|
||||
var invalidDataset = new carto.source.Dataset('invalid_dataset');
|
||||
return layer.setSource(invalidDataset);
|
||||
})
|
||||
.catch(function () {
|
||||
expect(sourceChangedSoy).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.setFeatureClickColumns', function () {
|
||||
var layer;
|
||||
var newColums;
|
||||
|
||||
beforeEach(function () {
|
||||
layer = new carto.layer.Layer(source, style);
|
||||
newColums = ['a', 'b'];
|
||||
});
|
||||
|
||||
it('should throw an error when the columns are not a valid parameter', function () {
|
||||
expect(function () {
|
||||
layer.setFeatureClickColumns([1, 2, 3]);
|
||||
}).toThrowError('The given object is not a valid array of string columns.');
|
||||
});
|
||||
|
||||
describe('when the layer hasn\'t been set an engine', function () {
|
||||
it('should normally add the columns', function () {
|
||||
layer.setFeatureClickColumns(newColums);
|
||||
|
||||
expect(layer.getFeatureClickColumns()).toEqual(newColums);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the layer has been set an engine', function () {
|
||||
var engineMock;
|
||||
|
||||
it('should normally add the columns', function (done) {
|
||||
engineMock = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload').and.returnValue(Promise.resolve()) };
|
||||
layer.$setEngine(engineMock);
|
||||
|
||||
layer.setFeatureClickColumns(newColums)
|
||||
.then(function () {
|
||||
var actualColumns = layer.getFeatureClickColumns();
|
||||
var expectedColumns = newColums;
|
||||
expect(actualColumns).toBeDefined();
|
||||
expect(actualColumns).toEqual(expectedColumns);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error when the columns are not valid', function (done) {
|
||||
engineMock = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload').and.returnValue(Promise.reject(new Error())) };
|
||||
layer.$setEngine(engineMock);
|
||||
|
||||
layer.setFeatureClickColumns(['wrong'])
|
||||
.catch(function (error) {
|
||||
expect(error instanceof Error).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fire an error event when the columns are not valid', function (done) {
|
||||
engineMock = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload').and.returnValue(Promise.reject(new Error())) };
|
||||
layer.$setEngine(engineMock);
|
||||
|
||||
var columnChangedError = jasmine.createSpy('columnChangedError');
|
||||
layer.on('error', columnChangedError);
|
||||
|
||||
layer.setFeatureClickColumns(['wrong'])
|
||||
.catch(function () {
|
||||
expect(columnChangedError).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.setFeatureOverColumns', function () {
|
||||
var layer;
|
||||
var newColums;
|
||||
|
||||
beforeEach(function () {
|
||||
layer = new carto.layer.Layer(source, style);
|
||||
newColums = ['a', 'b'];
|
||||
});
|
||||
|
||||
it('should throw an error when the columns are not a valid parameter', function () {
|
||||
expect(function () {
|
||||
layer.setFeatureOverColumns([1, 2, 3]);
|
||||
}).toThrowError('The given object is not a valid array of string columns.');
|
||||
});
|
||||
|
||||
describe('when the layer hasn\'t been set an engine', function () {
|
||||
it('should normally add the columns', function () {
|
||||
layer.setFeatureOverColumns(newColums);
|
||||
|
||||
expect(layer.getFeatureOverColumns()).toEqual(newColums);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the layer has been set an engine', function () {
|
||||
var engineMock;
|
||||
|
||||
it('should normally add the columns', function (done) {
|
||||
engineMock = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload').and.returnValue(Promise.resolve()) };
|
||||
layer.$setEngine(engineMock);
|
||||
|
||||
layer.setFeatureOverColumns(newColums)
|
||||
.then(function () {
|
||||
var actualColumns = layer.getFeatureOverColumns();
|
||||
var expectedColumns = newColums;
|
||||
expect(actualColumns).toBeDefined();
|
||||
expect(actualColumns).toEqual(expectedColumns);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error when the columns are not valid', function (done) {
|
||||
engineMock = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload').and.returnValue(Promise.reject(new Error())) };
|
||||
layer.$setEngine(engineMock);
|
||||
|
||||
layer.setFeatureOverColumns(['wrong'])
|
||||
.catch(function (error) {
|
||||
expect(error instanceof Error).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fire an error event when the columns are not valid', function (done) {
|
||||
engineMock = { on: jasmine.createSpy('on'), reload: jasmine.createSpy('reload').and.returnValue(Promise.reject(new Error())) };
|
||||
layer.$setEngine(engineMock);
|
||||
|
||||
var columnChangedError = jasmine.createSpy('columnChangedError');
|
||||
layer.on('error', columnChangedError);
|
||||
|
||||
layer.setFeatureOverColumns(['wrong'])
|
||||
.catch(function () {
|
||||
expect(columnChangedError).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.show', function () {
|
||||
it('should set the layer visibility to true', function () {
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
|
||||
layer.hide();
|
||||
|
||||
expect(layer.isVisible()).toEqual(false);
|
||||
expect(layer.isHidden()).toEqual(true);
|
||||
|
||||
layer.show();
|
||||
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
expect(layer.isHidden()).toEqual(false);
|
||||
});
|
||||
|
||||
it('should trigger a visibilityChanged event', function (done) {
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
|
||||
layer.hide();
|
||||
|
||||
layer.on('visibilityChanged', function () {
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
expect(layer.isHidden()).toEqual(false);
|
||||
done();
|
||||
});
|
||||
|
||||
layer.show();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.hide', function () {
|
||||
it('should set the layer visibility to false', function () {
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
|
||||
layer.hide();
|
||||
|
||||
expect(layer.isVisible()).toEqual(false);
|
||||
expect(layer.isHidden()).toEqual(true);
|
||||
});
|
||||
|
||||
it('should trigger a visibilityChanged event', function (done) {
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
|
||||
layer.on('visibilityChanged', function () {
|
||||
expect(layer.isVisible()).toEqual(false);
|
||||
expect(layer.isHidden()).toEqual(true);
|
||||
done();
|
||||
});
|
||||
|
||||
layer.hide();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.toggle', function () {
|
||||
it('should toggle the layer visibility', function () {
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
|
||||
layer.toggle();
|
||||
|
||||
expect(layer.isVisible()).toEqual(false);
|
||||
expect(layer.isHidden()).toEqual(true);
|
||||
|
||||
layer.toggle();
|
||||
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
expect(layer.isHidden()).toEqual(false);
|
||||
});
|
||||
|
||||
it('should trigger a visibilityChanged event', function (done) {
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
expect(layer.isVisible()).toEqual(true);
|
||||
|
||||
layer.on('visibilityChanged', function () {
|
||||
expect(layer.isVisible()).toEqual(false);
|
||||
expect(layer.isHidden()).toEqual(true);
|
||||
done();
|
||||
});
|
||||
|
||||
layer.toggle();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.setOrder', function () {
|
||||
it('should call moveLayer with the passed index', function () {
|
||||
var clientMock = { moveLayer: jasmine.createSpy('moveLayer') };
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
layer.$setClient(clientMock);
|
||||
|
||||
layer.setOrder(1);
|
||||
expect(clientMock.moveLayer).toHaveBeenCalledWith(layer, 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.bringToBack', function () {
|
||||
it('should call moveLayer with the passed index', function () {
|
||||
var clientMock = { moveLayer: jasmine.createSpy('moveLayer') };
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
layer.$setClient(clientMock);
|
||||
|
||||
layer.bringToBack();
|
||||
expect(clientMock.moveLayer).toHaveBeenCalledWith(layer, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.bringToFront', function () {
|
||||
it('should call moveLayer with the passed index', function () {
|
||||
var numberOfLayers = 3;
|
||||
var clientMock = { moveLayer: jasmine.createSpy('moveLayer'), _layers: { size: function () { return numberOfLayers; } } };
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
layer.$setClient(clientMock);
|
||||
|
||||
layer.bringToFront();
|
||||
expect(clientMock.moveLayer).toHaveBeenCalledWith(layer, numberOfLayers - 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.isInteractive', function () {
|
||||
it('returns true if layer has featureClickColumns', function () {
|
||||
const layer = new carto.layer.Layer(source, style, {
|
||||
featureClickColumns: ['cartodb_id']
|
||||
});
|
||||
|
||||
expect(layer.isInteractive()).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true if layer has featureOverColumns', function () {
|
||||
const layer = new carto.layer.Layer(source, style, {
|
||||
featureOverColumns: ['cartodb_id']
|
||||
});
|
||||
|
||||
expect(layer.isInteractive()).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false if layer doesn\'t have getFeatureClickColumns or getFeatureHoverColumns', function () {
|
||||
const layer = new carto.layer.Layer(source, style);
|
||||
|
||||
expect(layer.isInteractive()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
xit('should update "internalmodel.cartocss" when the style is updated', function (done) {
|
||||
var client = new carto.Client({
|
||||
apiKey: '84fdbd587e4a942510270a48e843b4c1baa11e18',
|
||||
username: 'cartojs-test'
|
||||
});
|
||||
var layer = new carto.layer.Layer(source, style);
|
||||
var newStyle = '#layer { marker-fill: #FABADA; }';
|
||||
|
||||
client.addLayer(layer)
|
||||
.then(function () {
|
||||
return style.setContent(newStyle);
|
||||
})
|
||||
.then(function () {
|
||||
expect(layer.$getInternalModel().get('cartocss')).toEqual(newStyle);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,230 @@
|
||||
var metadataParser = require('../../../../../../src/api/v4/layer/metadata/parser');
|
||||
|
||||
describe('api/v4/layer/metadata/parser', function () {
|
||||
describe('.getMetadataFromRules', function () {
|
||||
it('should parse correctly the range rules', function () {
|
||||
// From:
|
||||
// marker-width: ramp([scalerank], range(5, 20), quantiles(4));
|
||||
// marker-fill-opacity: ramp([pop_max], range(0,1), jenks);
|
||||
var rules = [
|
||||
{
|
||||
'selector': '#layer',
|
||||
'prop': 'marker-width',
|
||||
'column': 'scalerank',
|
||||
'mapping': '>',
|
||||
'buckets': [
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': 0,
|
||||
'end': 6
|
||||
},
|
||||
'value': 5
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': 6,
|
||||
'end': 7
|
||||
},
|
||||
'value': 10
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': 7,
|
||||
'end': 7
|
||||
},
|
||||
'value': 15
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': 7,
|
||||
'end': 10
|
||||
},
|
||||
'value': 20
|
||||
}
|
||||
],
|
||||
'stats': {
|
||||
'filter_avg': 6.642174269325321
|
||||
}
|
||||
},
|
||||
{
|
||||
'selector': '#layer',
|
||||
'prop': 'marker-fill-opacity',
|
||||
'column': 'pop_max',
|
||||
'mapping': '>',
|
||||
'buckets': [
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': -99,
|
||||
'end': 37945
|
||||
},
|
||||
'value': 0
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': 37945,
|
||||
'end': 138954
|
||||
},
|
||||
'value': 0.25
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': 138954,
|
||||
'end': 616990
|
||||
},
|
||||
'value': 0.5
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': 616990,
|
||||
'end': 2544000
|
||||
},
|
||||
'value': 0.75
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'type': 'range',
|
||||
'start': 2544000,
|
||||
'end': 35676000
|
||||
},
|
||||
'value': 1
|
||||
}
|
||||
],
|
||||
'stats': {
|
||||
'filter_avg': 322717.4763725758
|
||||
}
|
||||
}
|
||||
];
|
||||
var metadataList = metadataParser.getMetadataFromRules(rules);
|
||||
|
||||
expect(metadataList).toBeDefined();
|
||||
|
||||
expect(metadataList[0].getType()).toBe('buckets');
|
||||
expect(metadataList[0].getColumn()).toBe('scalerank');
|
||||
expect(metadataList[0].getMapping()).toBe('>');
|
||||
expect(metadataList[0].getProperty()).toBe('marker-width');
|
||||
expect(metadataList[0].getAverage()).toBe(6.642174269325321);
|
||||
expect(metadataList[0].getMin()).toBe(0);
|
||||
expect(metadataList[0].getMax()).toBe(10);
|
||||
expect(metadataList[0].getBuckets()).toEqual([
|
||||
{ min: 0, max: 6, value: 5 },
|
||||
{ min: 6, max: 7, value: 10 },
|
||||
{ min: 7, max: 7, value: 15 },
|
||||
{ min: 7, max: 10, value: 20 }
|
||||
]);
|
||||
|
||||
expect(metadataList[0].getType()).toBe('buckets');
|
||||
expect(metadataList[1].getColumn()).toBe('pop_max');
|
||||
expect(metadataList[1].getMapping()).toBe('>');
|
||||
expect(metadataList[1].getProperty()).toBe('marker-fill-opacity');
|
||||
expect(metadataList[1].getAverage()).toBe(322717.4763725758);
|
||||
expect(metadataList[1].getMin()).toBe(-99);
|
||||
expect(metadataList[1].getMax()).toBe(35676000);
|
||||
expect(metadataList[1].getBuckets()).toEqual([
|
||||
{ min: -99, max: 37945, value: 0 },
|
||||
{ min: 37945, max: 138954, value: 0.25 },
|
||||
{ min: 138954, max: 616990, value: 0.5 },
|
||||
{ min: 616990, max: 2544000, value: 0.75 },
|
||||
{ min: 2544000, max: 35676000, value: 1 }
|
||||
]);
|
||||
});
|
||||
|
||||
it('should parse correctly the category rules', function () {
|
||||
// From:
|
||||
// marker-fill: ramp([scalerank], (#5F4690, #1D6996, #38A6A5, #666666), (7, 6, 10), '=', category);
|
||||
// marker-file: ramp([scalerank], (url('https://s3.amazonaws.com/com.cartodb.users-assets.production/maki-icons/rail-light-18.svg'), url('https://s3.amazonaws.com/com.cartodb.users-assets.production/maki-icons/park-18.svg')), (7, 10), '=');
|
||||
var rules = [
|
||||
{
|
||||
'selector': '#layer',
|
||||
'prop': 'marker-fill',
|
||||
'column': 'scalerank',
|
||||
'mapping': '=',
|
||||
'buckets': [
|
||||
{
|
||||
'filter': {
|
||||
'name': 7,
|
||||
'type': 'category'
|
||||
},
|
||||
'value': '#5F4690'
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'name': 6,
|
||||
'type': 'category'
|
||||
},
|
||||
'value': '#1D6996'
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'name': 10,
|
||||
'type': 'category'
|
||||
},
|
||||
'value': '#38A6A5'
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'type': 'default'
|
||||
},
|
||||
'value': '#666666'
|
||||
}
|
||||
],
|
||||
'stats': {}
|
||||
},
|
||||
{
|
||||
'selector': '',
|
||||
'prop': 'marker-file',
|
||||
'column': 'scalerank',
|
||||
'mapping': '=',
|
||||
'buckets': [
|
||||
{
|
||||
'filter': {
|
||||
'name': 7,
|
||||
'type': 'category'
|
||||
},
|
||||
'value': 'url(\'https://s3.amazonaws.com/com.cartodb.users-assets.production/maki-icons/rail-light-18.svg\')'
|
||||
},
|
||||
{
|
||||
'filter': {
|
||||
'name': 10,
|
||||
'type': 'category'
|
||||
},
|
||||
'value': 'url(\'https://s3.amazonaws.com/com.cartodb.users-assets.production/maki-icons/park-18.svg\')'
|
||||
}
|
||||
],
|
||||
'stats': {}
|
||||
}
|
||||
];
|
||||
var metadataList = metadataParser.getMetadataFromRules(rules);
|
||||
|
||||
expect(metadataList).toBeDefined();
|
||||
|
||||
expect(metadataList[0].getType()).toBe('categories');
|
||||
expect(metadataList[0].getColumn()).toBe('scalerank');
|
||||
expect(metadataList[0].getMapping()).toBe('=');
|
||||
expect(metadataList[0].getProperty()).toBe('marker-fill');
|
||||
expect(metadataList[0].getDefaultValue()).toBe('#666666');
|
||||
expect(metadataList[0].getCategories()).toEqual([
|
||||
{ name: 7, value: '#5F4690' },
|
||||
{ name: 6, value: '#1D6996' },
|
||||
{ name: 10, value: '#38A6A5' }
|
||||
]);
|
||||
|
||||
expect(metadataList[0].getType()).toBe('categories');
|
||||
expect(metadataList[1].getColumn()).toBe('scalerank');
|
||||
expect(metadataList[1].getMapping()).toBe('=');
|
||||
expect(metadataList[1].getProperty()).toBe('marker-file');
|
||||
expect(metadataList[1].getDefaultValue()).not.toBeDefined();
|
||||
expect(metadataList[1].getCategories()).toEqual([
|
||||
{ name: 7, value: 'url(\'https://s3.amazonaws.com/com.cartodb.users-assets.production/maki-icons/rail-light-18.svg\')' },
|
||||
{ name: 10, value: 'url(\'https://s3.amazonaws.com/com.cartodb.users-assets.production/maki-icons/park-18.svg\')' }
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user