Files
carto.js/test/spec/api/v4/dataview/time-series.spec.js
T
2020-06-13 18:34:34 +08:00

428 lines
13 KiB
JavaScript

var Backbone = require('backbone');
var _ = require('underscore');
var carto = require('../../../../../src/api/v4/index');
var createEngine = require('../../../fixtures/engine.fixture.js');
function createHistogramInternalModelMock (options) {
options = options || {};
_.extend({
data: null,
nulls: null
}, options);
var internalModelMock = {
set: function () {},
get: function () {},
getUnfilteredDataModel: function () {},
getUnfilteredData: function () {
return [
{
freq: 23
}, {
freq: 46
}, {
}
];
},
getCurrentOffset: function () {
return 7200;
}
};
spyOn(internalModelMock, 'set');
spyOn(internalModelMock, 'get').and.callFake(function (key) {
if (key === 'data') {
return options.data;
}
if (key === 'nulls') {
return options.nulls;
}
if (key === 'totalAmount') {
return 7654;
}
});
spyOn(internalModelMock, 'getUnfilteredDataModel').and.returnValue({
get: function (key) {
if (key === 'nulls') {
return 12;
}
if (key === 'totalAmount') {
return 707;
}
}
});
_.extend(internalModelMock, Backbone.Events);
return internalModelMock;
}
function createSourceMock () {
return new carto.source.Dataset('ne_10m_populated_places_simple');
}
describe('api/v4/dataview/time-series', function () {
var source = createSourceMock();
describe('initialization', function () {
it('source must be provided', function () {
var test = function () {
new carto.dataview.TimeSeries(); // eslint-disable-line no-new
};
expect(test).toThrowError(Error, 'Source property is required.');
});
it('column must be provided', function () {
var test = function () {
new carto.dataview.TimeSeries(source); // eslint-disable-line no-new
};
expect(test).toThrowError(Error, 'Column property is required.');
});
it('options set to default if not provided', function () {
var column = 'population';
var dataview = new carto.dataview.TimeSeries(source, column);
expect(dataview._aggregation).toEqual(carto.dataview.timeAggregation.AUTO);
expect(dataview._offset).toBe(0);
expect(dataview._localTimezone).toBe(false);
});
it('options set to the provided value', function () {
var dataview = new carto.dataview.TimeSeries(source, 'population', {
aggregation: carto.dataview.timeAggregation.QUARTER,
offset: -7,
useLocalTimezone: true
});
expect(dataview._aggregation).toEqual(carto.dataview.timeAggregation.QUARTER);
expect(dataview._offset).toBe(-7 * 3600); // Internaly stored in seconds
expect(dataview._localTimezone).toBe(true);
});
it('throw error if aggregation is not a proper value', function () {
var test = function () {
new carto.dataview.TimeSeries(source, 'population', { // eslint-disable-line no-new
aggregation: 'terasecond'
});
};
expect(test).toThrowError(Error, 'Time aggregation must be a valid value. Use carto.dataview.timeAggregation.');
});
it('throw error if offset is not a valid hour', function () {
var test = function () {
new carto.dataview.TimeSeries(source, 'population', { // eslint-disable-line no-new
offset: 34
});
};
expect(test).toThrowError(Error, 'Offset must an integer value between -12 and 14.');
test = function () {
new carto.dataview.TimeSeries(source, 'population', { // eslint-disable-line no-new
offset: 10.45
});
};
expect(test).toThrowError(Error, 'Offset must an integer value between -12 and 14.');
});
it('throw error if localTimezone is not a binary value', function () {
var test = function () {
new carto.dataview.TimeSeries(source, 'population', { // eslint-disable-line no-new
useLocalTimezone: 'Los Angeles'
});
};
expect(test).toThrowError(Error, 'useLocalTimezone must be a boolean value.');
});
});
describe('.getData', function () {
var dataview;
beforeEach(function () {
dataview = new carto.dataview.TimeSeries(source, 'population');
});
it('returns null if there is no internalModel', function () {
var data = dataview.getData();
expect(data).toBeNull();
});
it('returns parsed data from the internal model', function () {
dataview._internalModel = createHistogramInternalModelMock({
data: [
{
freq: 35
}, {
freq: 50
}, {
}
],
nulls: 42
});
var data = dataview.getData();
expect(data.bins.length).toBe(3);
expect(data.bins[0].freq).toBe(35);
expect(data.bins[1].freq).toBe(50);
expect(data.bins[2].freq).toBeUndefined();
expect(data.bins[0].normalized).toBe(0.7);
expect(data.bins[1].normalized).toBe(1);
expect(data.bins[2].normalized).toBe(0);
expect(data.nulls).toBe(42);
expect(data.totalAmount).toBe(7654);
expect(data.offset).toBe(2);
});
it('returns nulls as 0 in case the internal model has no nulls', function () {
dataview._internalModel = createHistogramInternalModelMock({
data: [
{
freq: 35
}, {
freq: 50
}, {
}
],
nulls: undefined
});
var data = dataview.getData();
expect(data.bins.length).toBe(3);
expect(data.bins[0].freq).toBe(35);
expect(data.bins[1].freq).toBe(50);
expect(data.bins[2].freq).toBeUndefined();
expect(data.bins[0].normalized).toBe(0.7);
expect(data.bins[1].normalized).toBe(1);
expect(data.bins[2].normalized).toBe(0);
expect(data.nulls).toBe(0);
expect(data.totalAmount).toBe(7654);
});
it('returns null if internal model has no data', function () {
dataview._internalModel = createHistogramInternalModelMock();
var data = dataview.getData();
expect(data).toBe(null);
});
});
describe('.setAggregation', function () {
var dataview;
beforeEach(function () {
dataview = new carto.dataview.TimeSeries(source, 'population');
});
it('should validate aggregation', function () {
var test = function () {
dataview.setAggregation('terasecond');
};
expect(test).toThrowError(Error, 'Time aggregation must be a valid value. Use carto.dataview.timeAggregation.');
});
it('should set aggregation to internal model as well', function () {
dataview._internalModel = createHistogramInternalModelMock();
dataview.setAggregation(carto.dataview.timeAggregation.HOUR);
expect(dataview._internalModel.set).toHaveBeenCalledWith('aggregation', carto.dataview.timeAggregation.HOUR);
expect(dataview.getAggregation()).toBe('hour');
// Clean
dataview._internalModel = null;
});
it('should Trigger a aggregationChanged event when the aggregation are changed', function () {
var aggregationChangedSpy = jasmine.createSpy('aggregationChangedSpy');
dataview.on('aggregationChanged', aggregationChangedSpy);
expect(aggregationChangedSpy).not.toHaveBeenCalled();
dataview.$setEngine(createEngine());
dataview.setAggregation(carto.dataview.timeAggregation.HOUR);
expect(aggregationChangedSpy).toHaveBeenCalledWith(carto.dataview.timeAggregation.HOUR);
});
});
describe('.setOffset', function () {
var dataview;
beforeEach(function () {
dataview = new carto.dataview.TimeSeries(source, 'population');
});
it('should validate offset', function () {
var test = function () {
dataview.setOffset(32);
};
expect(test).toThrowError(Error, 'Offset must an integer value between -12 and 14.');
test = function () {
dataview.setOffset(10.7);
};
expect(test).toThrowError(Error, 'Offset must an integer value between -12 and 14.');
});
it('should set offset to internal model as well translated to seconds', function () {
dataview._internalModel = createHistogramInternalModelMock();
dataview.setOffset(-5);
expect(dataview._internalModel.set).toHaveBeenCalledWith('offset', -5 * 3600);
expect(dataview.getOffset()).toBe(-5);
// Clean
dataview._internalModel = null;
});
});
describe('.useLocalTimezone', function () {
var dataview;
beforeEach(function () {
dataview = new carto.dataview.TimeSeries(source, 'population');
});
it('should validate localTimezone', function () {
var test = function () {
dataview.useLocalTimezone('Compton');
};
expect(test).toThrowError(Error, 'useLocalTimezone must be a boolean value.');
});
it('should set localTimezone to internal model as well', function () {
dataview._internalModel = createHistogramInternalModelMock();
dataview.useLocalTimezone(true);
expect(dataview._internalModel.set).toHaveBeenCalledWith('localTimezone', true);
expect(dataview.isUsingLocalTimezone()).toBe(true);
// Clean
dataview._internalModel = null;
});
});
describe('.$setEngine', function () {
var engine;
var dataview;
beforeEach(function () {
dataview = new carto.dataview.TimeSeries(source, 'population');
engine = createEngine();
});
it('creates the internal model', function () {
dataview.disable(); // To test that it passes the ._enabled property to the internal model
dataview.setAggregation(carto.dataview.timeAggregation.WEEK);
dataview.setOffset(6);
dataview.useLocalTimezone(true);
dataview.$setEngine(engine);
var internalModel = dataview.$getInternalModel();
expect(internalModel.get('source')).toBe(dataview._source.$getInternalModel());
expect(internalModel.get('column')).toEqual(dataview._column);
expect(internalModel.get('aggregation')).toBe('week');
expect(internalModel.get('localTimezone')).toBe(true);
expect(internalModel.get('offset')).toBe(6 * 3600);
expect(internalModel.isEnabled()).toBe(false);
expect(internalModel._engine).toBe(engine);
});
it('calling twice to $setEngine does not create another internalModel', function () {
spyOn(dataview, '_createInternalModel').and.callThrough();
dataview.$setEngine(engine);
dataview.$setEngine(engine);
expect(dataview._createInternalModel.calls.count()).toBe(1);
});
describe('spatial filters', function () {
it('creates the internal model with BoundingBox filter if provided', function () {
var filter = new carto.filter.BoundingBox();
dataview.addFilter(filter);
dataview.$setEngine(engine);
var internalModel = dataview.$getInternalModel();
expect(internalModel._bboxFilter).toBeDefined();
expect(internalModel.syncsOnBoundingBoxChanges()).toBe(true);
});
it('allows removing a BoundingBox filter', function () {
var filter = new carto.filter.BoundingBox();
dataview.addFilter(filter);
dataview.$setEngine(engine);
expect(dataview.hasFilter(filter)).toBe(true);
dataview.removeFilter(filter);
expect(dataview.hasFilter(filter)).toBe(false);
var internalModel = dataview.$getInternalModel();
expect(internalModel._bboxFilter).toBeNull();
expect(internalModel.syncsOnBoundingBoxChanges()).toBe(false);
});
it('creates the internal model with Circle filter if provided', function () {
var filter = new carto.filter.Circle();
dataview.addFilter(filter);
dataview.$setEngine(engine);
var internalModel = dataview.$getInternalModel();
expect(internalModel._circleFilter).toBeDefined();
expect(internalModel.syncsOnCircleChanges()).toBe(true);
});
it('allows removing a Circle filter', function () {
var filter = new carto.filter.Circle();
dataview.addFilter(filter);
dataview.$setEngine(engine);
expect(dataview.hasFilter(filter)).toBe(true);
dataview.removeFilter(filter);
expect(dataview.hasFilter(filter)).toBe(false);
var internalModel = dataview.$getInternalModel();
expect(internalModel._circleFilter).toBeNull();
expect(internalModel.syncsOnCircleChanges()).toBe(false);
});
it('creates the internal model with Polygon filter if provided', function () {
var filter = new carto.filter.Polygon();
dataview.addFilter(filter);
dataview.$setEngine(engine);
var internalModel = dataview.$getInternalModel();
expect(internalModel._polygonFilter).toBeDefined();
expect(internalModel.syncsOnPolygonChanges()).toBe(true);
});
it('allows removing a Polygon filter', function () {
var filter = new carto.filter.Polygon();
dataview.addFilter(filter);
dataview.$setEngine(engine);
expect(dataview.hasFilter(filter)).toBe(true);
dataview.removeFilter(filter);
expect(dataview.hasFilter(filter)).toBe(false);
var internalModel = dataview.$getInternalModel();
expect(internalModel._polygonFilter).toBeNull();
expect(internalModel.syncsOnPolygonChanges()).toBe(false);
});
});
});
});