cartodb/carto.js/test/spec/dataviews/histogram-dataview-model.spec.js
2020-06-15 10:58:47 +08:00

987 lines
30 KiB
JavaScript

var Backbone = require('backbone');
var WindshaftFiltersRange = require('../../../src/windshaft/filters/range');
var WindshaftFiltersBoundingBox = require('../../../src/windshaft/filters/bounding-box');
var WindshaftFiltersCircle = require('../../../src/windshaft/filters/circle');
var WindshaftFiltersPolygon = require('../../../src/windshaft/filters/polygon');
var HistogramDataviewModel = require('../../../src/dataviews/histogram-dataview-model');
var MapModelBoundingBoxAdapter = require('../../../src/geo/adapters/map-model-bounding-box-adapter');
var helper = require('../../../src/dataviews/helpers/histogram-helper');
var MockFactory = require('../../helpers/mockFactory');
var createEngine = require('../fixtures/engine.fixture.js');
function randomString (length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
describe('dataviews/histogram-dataview-model', function () {
var engineMock;
var apiKeyQueryParam;
beforeEach(function () {
this.map = jasmine.createSpyObj('map', ['getViewBounds', 'on']);
this.map.getViewBounds.and.returnValue([[1, 2], [3, 4]]);
engineMock = createEngine({});
apiKeyQueryParam = 'api_key=' + engineMock.getApiKey();
this.filter = new WindshaftFiltersRange();
this.bboxFilter = new WindshaftFiltersBoundingBox(new MapModelBoundingBoxAdapter(this.map));
spyOn(HistogramDataviewModel.prototype, 'listenTo').and.callThrough();
spyOn(HistogramDataviewModel.prototype, 'fetch').and.callThrough();
spyOn(HistogramDataviewModel.prototype, '_updateBindings');
spyOn(HistogramDataviewModel.prototype, '_resetFilterAndFetch');
this.source = MockFactory.createAnalysisModel({ id: 'a0' });
this.model = new HistogramDataviewModel({
source: this.source
}, {
engine: engineMock,
filter: this.filter,
bboxFilter: this.bboxFilter
});
});
it('defaults', function () {
expect(this.model.get('type')).toBe('histogram');
expect(this.model.get('totalAmount')).toBe(0);
expect(this.model.get('filteredAmount')).toBe(0);
expect(this.model.get('hasNulls')).toBe(false);
expect(this.model.get('localTimezone')).toBe(false);
});
it('after calling _initBinds, we must listen to changes in URL', function () {
spyOn(this.model, '_onUrlChanged');
this.model._initBinds();
this.model.set('url', randomString(32, 'abcdefghijk'));
expect(this.model._onUrlChanged).toHaveBeenCalled();
});
it('should not listen any url change from the beginning', function () {
this.model.set('url', 'https://carto.com');
expect(this.model.fetch).not.toHaveBeenCalled();
});
it('should set unfiltered model url when model has changed it', function () {
spyOn(this.model._totals, 'setUrl');
this.model.set('url', 'hey!');
expect(this.model._totals.setUrl).toHaveBeenCalled();
});
it('should set the api_key attribute on the internal models', function () {
this.model = new HistogramDataviewModel({
source: this.source
}, {
engine: engineMock,
filter: this.filter,
bboxFilter: this.bboxFilter
});
expect(this.model._totals.get('apiKey')).toEqual(engineMock.getApiKey());
});
describe('should get the correct histogram shape', function () {
beforeEach(function () {
this.model.set('bins', 6);
});
it('when it is flat', function () {
this.model.set('data', [
{ bin: 0, freq: 25 },
{ bin: 1, freq: 26 },
{ bin: 2, freq: 25 },
{ bin: 3, freq: 26 },
{ bin: 4, freq: 26 },
{ bin: 5, freq: 25 }
]);
expect(this.model.getDistributionType()).toEqual('F');
});
it('when it is A', function () {
this.model.set('data', [
{ bin: 0, freq: 0 },
{ bin: 1, freq: 5 },
{ bin: 2, freq: 25 },
{ bin: 3, freq: 18 },
{ bin: 4, freq: 8 },
{ bin: 5, freq: 2 }
]);
expect(this.model.getDistributionType()).toEqual('A');
});
it('when it is J', function () {
this.model.set('data', [
{ bin: 0, freq: 0 },
{ bin: 1, freq: 2 },
{ bin: 2, freq: 5 },
{ bin: 3, freq: 8 },
{ bin: 4, freq: 18 },
{ bin: 5, freq: 25 }
]);
expect(this.model.getDistributionType()).toEqual('J');
});
it('when it is L', function () {
this.model.set('data', [
{ bin: 0, freq: 25 },
{ bin: 1, freq: 18 },
{ bin: 4, freq: 8 },
{ bin: 2, freq: 5 },
{ bin: 5, freq: 2 },
{ bin: 3, freq: 0 }
]);
expect(this.model.getDistributionType()).toEqual('L');
});
xit('when it is clustered', function () {
this.model.set('data', [
{ bin: 0, freq: 20 },
{ bin: 1, freq: 18 },
{ bin: 2, freq: 5 },
{ bin: 3, freq: 0 },
{ bin: 4, freq: 32 },
{ bin: 5, freq: 16 }
]);
expect(this.model.getDistributionType()).toEqual('C');
});
});
describe('when _totals changes:data', function () {
beforeEach(function () {
var histogramData = {
bin_width: 10,
bins_count: 3,
bins_start: 12,
nulls: 0,
aggregation: 'quarter'
};
spyOn(this.model._totals, 'sync').and.callFake(function (method, model, options) {
options.success(histogramData);
});
});
it('should set start, end, bins and aggregation', function () {
expect(this.model.get('start')).toBeUndefined();
expect(this.model.get('end')).toBeUndefined();
this.model._totals.fetch();
expect(this.model.get('start')).toEqual(12);
expect(this.model.get('end')).toEqual(42);
expect(this.model.get('bins')).toEqual(3);
expect(this.model.get('aggregation')).toEqual('quarter');
});
it('should call _updateBindings only once', function () {
this.model._totals.fetch();
expect(this.model._updateBindings).toHaveBeenCalled();
this.model._updateBindings.calls.reset();
this.model._totals.fetch();
expect(this.model._updateBindings).not.toHaveBeenCalled();
});
});
describe('when totals has an error', function () {
it('dataview status is set to error and status error is properly triggered', function () {
var ajaxResponse = {
readyState: 4,
responseText: '{"errors":["column unknown_column does not exist"],"errors_with_context":[{"type":"unknown","message":"column unknown_column does not exist"}]}',
responseJSON: {
errors: [
'column "unknown_column" does not exist'
],
errors_with_context: [
{
type: 'unknown',
message: 'column unknown_column does not exist'
}
]
},
status: 404,
statusText: 'Not Found'
};
var capturedError = null;
this.model.on('statusError', function (model, error) {
capturedError = error;
});
this.model._totals.trigger('error', this.model._totals, ajaxResponse);
expect(this.model.get('status')).toEqual('error');
expect(capturedError.message).toEqual('column unknown_column does not exist');
});
});
describe('when column changes', function () {
it('should set column_type to original data, set undefined aggregation, reload map and call _onUrlChanged', function () {
engineMock.reload.calls.reset();
this.model.set({
aggregation: 'quarter',
column: 'random_col',
column_type: 'aColumnType'
});
expect(this.model._totals.get('column_type')).toEqual('aColumnType');
expect(this.model.get('aggregation')).toBeUndefined();
expect(engineMock.reload).toHaveBeenCalledWith({ forceFetch: true, sourceId: 'a0' });
});
});
describe('parse', function () {
it('should parse the bins', function () {
var data = {
bin_width: 14490.25,
bins: [
{ bin: 0, freq: 2, max: 70151, min: 55611 },
{ bin: 1, freq: 2, max: 79017, min: 78448 },
{ bin: 3, freq: 1, max: 113572, min: 113572 }
],
bins_count: 4,
bins_start: 55611,
nulls: 1,
type: 'histogram'
};
this.model.parse(data);
var parsedData = this.model.getData();
expect(data.nulls).toBe(1);
expect(parsedData.length).toBe(4);
expect(JSON.stringify(parsedData)).toBe('[{"bin":0,"start":55611,"end":70101.25,"freq":2,"max":70151,"min":55611},{"bin":1,"start":70101.25,"end":84591.5,"freq":2,"max":79017,"min":78448},{"bin":2,"start":84591.5,"end":99081.75,"freq":0},{"bin":3,"start":99081.75,"end":113572,"freq":1,"max":113572,"min":113572}]');
});
it('should set hasNulls to true if null is set in the response', function () {
var data = {
bin_width: 14490.25,
bins: [
{ bin: 0, freq: 2, max: 70151, min: 55611 },
{ bin: 1, freq: 2, max: 79017, min: 78448 },
{ bin: 3, freq: 1, max: 113572, min: 113572 }
],
bins_count: 4,
bins_start: 55611,
nulls: 0,
type: 'histogram'
};
var model = new HistogramDataviewModel({
source: this.source
}, {
engine: engineMock,
filter: this.filter,
bboxFilter: this.bboxFilter
});
model.set(model.parse(data));
expect(model.hasNulls()).toBe(true);
});
it('should set hasNulls to false if null is undefined in the response', function () {
var data = {
bin_width: 14490.25,
bins: [
{ bin: 0, freq: 2, max: 70151, min: 55611 },
{ bin: 1, freq: 2, max: 79017, min: 78448 },
{ bin: 3, freq: 1, max: 113572, min: 113572 }
],
bins_count: 4,
bins_start: 55611,
type: 'histogram'
};
var model = new HistogramDataviewModel({
source: this.source
}, {
engine: engineMock,
filter: this.filter,
bboxFilter: this.bboxFilter
});
model.set(model.parse(data));
model._totals = new Backbone.Model({ aggregation: 'quarter' });
expect(model.hasNulls()).toBe(false);
});
it('should calculate total amount and filtered amount in parse when a filter is present', function () {
var data = {
bin_width: 1,
bins: [
{ bin: 0, freq: 2 },
{ bin: 1, freq: 3 },
{ bin: 2, freq: 7 }
],
bins_count: 3,
bins_start: 1,
nulls: 0,
type: 'histogram'
};
this.model.filter = new WindshaftFiltersRange({ min: 1, max: 3 });
var parsedData = this.model.parse(data);
expect(parsedData.totalAmount).toBe(12);
expect(parsedData.filteredAmount).toBe(5);
});
it('should calculate only total amount in parse when there is no filter', function () {
var data = {
bin_width: 1,
bins: [
{ bin: 0, freq: 2 },
{ bin: 1, freq: 3 },
{ bin: 2, freq: 7 }
],
bins_count: 3,
bins_start: 1,
nulls: 0,
type: 'histogram'
};
var parsedData = this.model.parse(data);
expect(parsedData.totalAmount).toBe(12);
expect(parsedData.filteredAmount).toBe(0);
});
it('parser do not fails when there are no bins', function () {
var data = {
bin_width: 0,
bins: [],
bins_count: 0,
bins_start: 0,
nulls: 0,
type: 'histogram'
};
this.model.parse(data);
var parsedData = this.model.getData();
expect(data.nulls).toBe(0);
expect(parsedData.length).toBe(0);
});
it('should parse the bins and fix end bucket issues', function () {
var data = {
bin_width: 1041.66645833333,
bins_count: 48,
bins_start: 0.01,
nulls: 0,
avg: 55.5007561961441,
bins: [{
bin: 47,
min: 50000,
max: 50000,
avg: 50000,
freq: 6
// NOTE - The end of this bucket is 48 * 1041.66645833333 = 49999.98999999984
// but it must be corrected to 50.000.
}],
type: 'histogram'
};
this.model.parse(data);
var parsedData = this.model.getData();
expect(data.nulls).toBe(0);
expect(parsedData.length).toBe(48);
expect(parsedData[47].end).not.toBeLessThan(parsedData[47].max);
});
it('should call .fillNumericBuckets if aggregation is not present', function () {
spyOn(helper, 'fillNumericBuckets');
this.model._initBinds();
this.model.set('column_type', 'number');
var data = {
bin_width: 0,
bins: [],
bins_count: 0,
bins_start: 0,
nulls: 0,
type: 'histogram'
};
this.model.parse(data);
expect(helper.fillNumericBuckets).toHaveBeenCalled();
});
it('should call .fillTimestampBuckets if aggregation is present', function () {
spyOn(helper, 'fillTimestampBuckets').and.callThrough();
this.model._initBinds();
this.model.set({
aggregation: 'minute',
column_type: 'date'
}, { silent: true });
var data = {
aggregation: 'minute',
offset: 3600,
timestamp_start: 1496690940,
bin_width: 59.5833333333333,
bins_count: 2,
bins_start: 1496690940,
nulls: 0,
bins: [
{
bin: 0,
timestamp: 1496690940,
min: 1496690944,
max: 1496690999,
avg: 1496690971.58824,
freq: 17
},
{
bin: 1,
timestamp: 1496691000,
min: 1496691003,
max: 1496691059,
avg: 1496691031.22222,
freq: 18
}
],
type: 'histogram'
};
var parsedData = this.model.parse(data);
expect(helper.fillTimestampBuckets).toHaveBeenCalled();
expect(JSON.stringify(parsedData)).toBe('{"data":[{"bin":0,"start":1496690940,"end":1496690999,"next":1496691000,"freq":17,"min":1496690944,"max":1496690999,"avg":1496690971.58824},{"bin":1,"start":1496691000,"end":1496691059,"next":1496691060,"freq":18,"min":1496691003,"max":1496691059,"avg":1496691031.22222}],"filteredAmount":0,"nulls":0,"totalAmount":35,"bins":2,"hasNulls":true}');
});
});
describe('when column_type changes', function () {
beforeEach(function () {
expect(this.model.filter.get('column_type')).not.toEqual('date');
this.model.set('column_type', 'date');
});
it('should change the filter column_type', function () {
expect(this.model.filter.get('column_type')).toEqual('date');
});
});
describe('.url', function () {
beforeEach(function () {
this.model.set('url', 'http://example.com');
});
it('should include bbox', function () {
expect(this.model.url()).toEqual('http://example.com?bbox=2,1,4,3&' + apiKeyQueryParam);
});
it('should include circle filter', function () {
var filter = new WindshaftFiltersCircle();
var circle = {lat: 1, lng: 2, radius: 3};
filter.setCircle(circle);
this.model = new HistogramDataviewModel({
source: this.source
}, {
engine: engineMock,
circleFilter: filter
});
// DataviewModel defaults set this prop to true, even for cases like this not requiring passing a bbox filter
this.model.set('sync_on_bbox_change', false);
var circleEncoded = encodeURIComponent(JSON.stringify(circle));
expect(this.model.set('url', 'http://example.com'));
expect(this.model.url()).toEqual('http://example.com?circle=' + circleEncoded + '&' + apiKeyQueryParam);
});
it('should update circle filter', function () {
var filter = new WindshaftFiltersCircle();
var circle = {lat: 1, lng: 2, radius: 3};
filter.setCircle(circle);
this.model = new HistogramDataviewModel({
source: this.source
}, {
engine: engineMock,
circleFilter: filter
});
// DataviewModel defaults set this prop to true, even for cases like this not requiring passing a bbox filter
this.model.set('sync_on_bbox_change', false);
// updated!
var updatedCircle = {lat: 10, lng: 20, radius: 30};
filter.setCircle(updatedCircle);
var updatedCircleEncoded = encodeURIComponent(JSON.stringify(updatedCircle));
expect(this.model.set('url', 'http://example.com'));
expect(this.model.url()).toEqual('http://example.com?circle=' + updatedCircleEncoded + '&' + apiKeyQueryParam);
});
it('should include polygon filter, plus other required params', function () {
var filter = new WindshaftFiltersPolygon();
var polygon = { type: 'Polygon', coordinates: [[1, 2], [3, 4], [5, 6], [1, 2]] };
filter.setPolygon(polygon);
this.model = new HistogramDataviewModel({
source: this.source
}, {
engine: engineMock,
polygonFilter: filter
});
// DataviewModel defaults set this prop to true, even for cases like this not requiring passing a bbox filter
this.model.set('sync_on_bbox_change', false);
var polygonEncoded = encodeURIComponent(JSON.stringify(polygon));
expect(this.model.set('url', 'http://example.com'));
expect(this.model.url()).toEqual('http://example.com?polygon=' + polygonEncoded + '&' + apiKeyQueryParam);
});
it('should update polygon filter', function () {
var filter = new WindshaftFiltersPolygon();
var polygon = { type: 'Polygon', coordinates: [[1, 2], [3, 4], [5, 6], [1, 2]] };
filter.setPolygon(polygon);
this.model = new HistogramDataviewModel({
source: this.source
}, {
engine: engineMock,
polygonFilter: filter
});
// DataviewModel defaults set this prop to true, even for cases like this not requiring passing a bbox filter
this.model.set('sync_on_bbox_change', false);
// updated!
var updatedPolygon = { type: 'Polygon', coordinates: [[10, 20], [30, 40], [50, 60], [10, 20]] };
filter.setPolygon(updatedPolygon);
var updatedPolygonEncoded = encodeURIComponent(JSON.stringify(updatedPolygon));
expect(this.model.set('url', 'http://example.com'));
expect(this.model.url()).toEqual('http://example.com?polygon=' + updatedPolygonEncoded + '&' + apiKeyQueryParam);
});
describe('column type is number', function () {
describe('if bins present', function () {
it('should include start and end if present', function () {
this.model.set({
bins: 33,
start: 11,
end: 22,
column_type: 'number'
});
expect(this.model.url()).toEqual('http://example.com?bbox=2,1,4,3&bins=33&start=11&end=22&' + apiKeyQueryParam);
});
it('should include bins', function () {
this.model.set({
bins: 33,
column_type: 'number'
});
expect(this.model.url()).toEqual('http://example.com?bbox=2,1,4,3&bins=33&' + apiKeyQueryParam);
});
});
it('should not include start, end and bins when own_filter is enabled', function () {
this.model.set({
url: 'http://example.com',
start: 0,
end: 10,
bins: 25,
column_type: 'number'
});
expect(this.model.url()).toEqual('http://example.com?bbox=2,1,4,3&bins=25&start=0&end=10&' + apiKeyQueryParam);
this.model.enableFilter();
expect(this.model.url()).toEqual('http://example.com?bbox=2,1,4,3&own_filter=1&bins=25&' + apiKeyQueryParam);
});
});
describe('column type is date', function () {
it('should only include aggregation if aggregation and bins present', function () {
this.model.set({
aggregation: 'month',
bins: 33,
column_type: 'date'
});
expect(this.model.url()).toEqual('http://example.com?bbox=2,1,4,3&aggregation=month&' + apiKeyQueryParam);
});
it('should include aggregation auto if column type is date and no aggregation set', function () {
this.model.set({
aggregation: undefined,
column_type: 'date'
});
expect(this.model.url()).toEqual('http://example.com?bbox=2,1,4,3&aggregation=auto&' + apiKeyQueryParam);
});
it('should use offset if present', function () {
this.model.set({
aggregation: 'month',
column_type: 'date',
offset: 7200,
localTimezone: false
}, { silent: true });
var url = this.model.url();
expect(url).toEqual('http://example.com?bbox=2,1,4,3&aggregation=month&offset=7200&' + apiKeyQueryParam);
});
it('should use local offset if localTimezone is true', function () {
this.model.set({
aggregation: 'month',
column_type: 'date',
offset: 7200,
localTimezone: true
}, { silent: true });
this.model._localOffset = 43200;
var url = this.model.url();
expect(url).toEqual('http://example.com?bbox=2,1,4,3&aggregation=month&offset=43200&' + apiKeyQueryParam);
});
});
});
describe('.toJSON', function () {
beforeEach(function () {
this.model.set('column', 'updated_at', { silent: true });
spyOn(this.model, 'getSourceId').and.returnValue('g4');
});
it('should return no bins if column is number and bins undefined', function () {
this.model.set({
column_type: 'number',
bins: undefined
}, { silent: true });
var json = this.model.toJSON();
expect(json).toEqual({
type: 'histogram',
source: { id: 'g4' },
options: {
column: 'updated_at'
}
});
});
it('should return bins if column is number and bins defined', function () {
this.model.set({
column_type: 'number',
bins: 808
}, { silent: true });
var json = this.model.toJSON();
expect(json).toEqual({
type: 'histogram',
source: { id: 'g4' },
options: {
column: 'updated_at',
bins: 808
}
});
});
it('should return auto if column is date and aggregation undefined', function () {
this.model.set({
column_type: 'date',
aggregation: undefined
}, { silent: true });
var json = this.model.toJSON();
expect(json).toEqual({
type: 'histogram',
source: { id: 'g4' },
options: {
column: 'updated_at',
aggregation: 'auto'
}
});
});
it('should return aggregation if column is date and aggregation defined', function () {
this.model.set({
column_type: 'date',
aggregation: 'minute'
}, { silent: true });
var json = this.model.toJSON();
expect(json).toEqual({
type: 'histogram',
source: { id: 'g4' },
options: {
column: 'updated_at',
aggregation: 'minute'
}
});
});
});
describe('.enableFilter', function () {
it('should set the own_filter attribute', function () {
expect(this.model.get('own_filter')).toBeUndefined();
this.model.enableFilter();
expect(this.model.get('own_filter')).toEqual(1);
});
});
describe('.disableFilter', function () {
it('should unset the own_filter attribute', function () {
this.model.enableFilter();
this.model.disableFilter();
expect(this.model.get('own_filter')).toBeUndefined();
});
});
describe('._onColumnChanged', function () {
it('should unset aggregation, and call _reloadAndForceFetch', function () {
engineMock.reload.calls.reset();
this.model.set({
column: 'time',
aggregation: 'week',
offset: 3600
});
this.model._onColumnChanged();
expect(engineMock.reload).toHaveBeenCalled();
expect(this.model.get('aggregation')).toBeUndefined();
});
it('should reset totals start and end values', function () {
spyOn(this.model._totals, 'sync').and.callFake(function (method, model, options) {
options.success({
bin_width: 10,
bins_count: 3,
bins_start: 12,
nulls: 0,
aggregation: 'quarter'
});
});
this.model._totals.fetch();
expect(this.model._totals.get('start')).toEqual(12);
expect(this.model._totals.get('end')).toEqual(42);
this.model.set({
column: 'time',
aggregation: 'week',
offset: 3600
});
this.model._onColumnChanged();
expect(this.model._totals.get('start')).toBeNull();
expect(this.model._totals.get('end')).toBeNull();
});
});
describe('._calculateTotalAmount', function () {
it('should aggregate all bucket frequencies', function () {
var buckets = [
{ freq: 8 },
{ freq: 7 },
{ freq: 0 },
{ freq: 3 }
];
var result = this.model._calculateTotalAmount(buckets);
expect(result).toEqual(18);
});
it('should return 0 if no buckets present', function () {
var buckets = [];
var result = this.model._calculateTotalAmount(buckets);
expect(result).toEqual(0);
});
it('should calculate totals properly even if no bucket is present in the middle', function () {
var buckets = [
{ freq: 8 },
null,
{ freq: 0 },
{ max: 6 },
{ freq: 3 }
];
var result = this.model._calculateTotalAmount(buckets);
expect(result).toEqual(11);
});
});
describe('._onTotalsDataFetched', function () {
beforeEach(function () {
});
it('should be called callwhen totals data has been fetched', function () {
spyOn(this.model, '_onTotalsDataFetched');
this.model._totals.off('loadModelCompleted', null, this.model);
this.model._initBinds();
this.model._totals.trigger('loadModelCompleted');
expect(this.model._onTotalsDataFetched).toHaveBeenCalled();
});
it('should call _resetFilterAndFetch if column is date and aggregation', function () {
var model = new Backbone.Model({
aggregation: 'week'
});
this.model.set('column_type', 'date', { silent: true });
this.model._onTotalsDataFetched(null, model);
expect(this.model._resetFilterAndFetch).toHaveBeenCalled();
});
it('should call _resetFilterAndFetch if column is date and offset changes', function () {
var model = new Backbone.Model({
offset: 3600
});
this.model.set('column_type', 'date', { silent: true });
this.model._onTotalsDataFetched(null, model);
expect(this.model._resetFilterAndFetch).toHaveBeenCalled();
});
it('should call _resetFilterAndFetch if column is number and bins changes', function () {
var model = new Backbone.Model({
bins: 5
});
this.model.set('column_type', 'number', { silent: true });
this.model._onTotalsDataFetched(null, model);
expect(this.model._resetFilterAndFetch).toHaveBeenCalled();
});
it('should call only fetch in the rest of cases', function () {
var model = new Backbone.Model({
start: this.model.get('start') + 1,
end: 22
});
this.model._onTotalsDataFetched(null, model);
expect(this.model.fetch).toHaveBeenCalled();
});
it('should set the data fetched', function () {
var model = new Backbone.Model({
bins: 5,
start: 11,
end: 22
});
this.model._onTotalsDataFetched(null, model);
expect(this.model.get('start')).toEqual(11);
expect(this.model.get('end')).toEqual(22);
expect(this.model.get('bins')).toEqual(5);
});
});
describe('change local timezone', function () {
it('should set the same value to originalData', function () {
var originalValue = this.model.get('localTimezone');
this.model._totals.set('localTimezone', originalValue, { silent: true });
this.model.set('localTimezone', !originalValue);
expect(this.model._totals.get('localTimezone')).toBe(this.model.get('localTimezone'));
});
});
describe('.getCurrentOffset', function () {
beforeEach(function () {
this.model.set('offset', 7200, { silent: true });
this.model._localOffset = 43200;
});
it('should return offset if `localTimezone` is not set', function () {
this.model.set('localTimezone', false, { silent: true });
var offset = this.model.getCurrentOffset();
expect(offset).toBe(7200);
});
it('should return local offset if `localTimezone` is set', function () {
this.model.set('localTimezone', true, { silent: true });
var offset = this.model.getCurrentOffset();
expect(offset).toBe(43200);
});
});
describe('_.onFieldsChanged', function () {
it('should set bins of totals if bins are changed in a number column', function () {
this.model.set({
bins: 808,
column_type: 'number'
}, { silent: true });
this.model._totals.set({ bins: 808 }, { silent: true });
this.model.set({ bins: 303 });
expect(this.model._totals.get('bins')).toBe(303);
});
it('should not set bins of totals if bins are changed because of a column change', function () {
this.model.set({
bins: 808,
aggregation: 'week',
column_type: 'number'
}, { silent: true });
this.model._totals.set({ bins: 808 }, { silent: true });
this.model.set({ bins: 303, aggregation: undefined });
expect(this.model._totals.get('bins')).toBe(808);
});
it('should set offset and aggregation of totals if bins are changed in a date column', function () {
this.model.set({
offset: 7200,
aggregation: 'week',
column_type: 'date'
}, { silent: true });
this.model._totals.set({
offset: 7200,
aggregation: 'week'
}, { silent: true });
this.model.set({ aggregation: 'month', offset: 3600 });
expect(this.model._totals.get('aggregation')).toBe('month');
expect(this.model._totals.get('offset')).toBe(3600);
});
});
});