562 lines
17 KiB
JavaScript
562 lines
17 KiB
JavaScript
|
var specHelper = require('../spec-helper');
|
||
|
var WidgetModel = require('../../../../javascripts/deep-insights/widgets/widget-model');
|
||
|
var Backbone = require('backbone');
|
||
|
var _ = require('underscore');
|
||
|
|
||
|
describe('widgets/widget-model', function () {
|
||
|
describe('dataview enabled', function () {
|
||
|
var dataviewModel;
|
||
|
var layerModel;
|
||
|
|
||
|
beforeEach(function () {
|
||
|
var vis = specHelper.createDefaultVis();
|
||
|
var source = vis.analysis.findNodeById('a0');
|
||
|
|
||
|
// Use a category dataview as example
|
||
|
dataviewModel = vis.dataviews.createCategoryModel({
|
||
|
column: 'col',
|
||
|
source: source
|
||
|
});
|
||
|
|
||
|
layerModel = new Backbone.Model({
|
||
|
id: 'first-layer',
|
||
|
type: 'torque',
|
||
|
visible: false
|
||
|
});
|
||
|
|
||
|
this.model = new WidgetModel(null, {
|
||
|
dataviewModel: dataviewModel,
|
||
|
layerModel: layerModel
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should be enabled always although layer is not visible', function () {
|
||
|
expect(dataviewModel.get('enabled')).toBeTruthy();
|
||
|
});
|
||
|
|
||
|
it('should not change enable attribute although layer visibility changes', function () {
|
||
|
layerModel.set('visible', true);
|
||
|
expect(dataviewModel.get('enabled')).toBeTruthy();
|
||
|
layerModel.set('visible', false);
|
||
|
expect(dataviewModel.get('enabled')).toBeTruthy();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('when autostyle options is enabled', function () {
|
||
|
var dataviewModel;
|
||
|
var layerModel;
|
||
|
|
||
|
beforeEach(function () {
|
||
|
var vis = specHelper.createDefaultVis();
|
||
|
var source = vis.analysis.findNodeById('a0');
|
||
|
|
||
|
// Use a category dataview as example
|
||
|
dataviewModel = vis.dataviews.createCategoryModel({
|
||
|
column: 'col',
|
||
|
source: source
|
||
|
});
|
||
|
dataviewModel.remove = spyOn(dataviewModel, 'remove');
|
||
|
layerModel = new Backbone.Model({
|
||
|
id: 'first-layer',
|
||
|
type: 'torque',
|
||
|
visible: true
|
||
|
});
|
||
|
|
||
|
this.model = new WidgetModel(null, {
|
||
|
dataviewModel: dataviewModel,
|
||
|
layerModel: layerModel
|
||
|
}, {autoStyleEnabled: true});
|
||
|
});
|
||
|
|
||
|
describe('.update', function () {
|
||
|
beforeEach(function () {
|
||
|
this.widgetChangeSpy = jasmine.createSpy('widgetModel change');
|
||
|
this.model.on('change', this.widgetChangeSpy);
|
||
|
});
|
||
|
|
||
|
describe('when given empty object', function () {
|
||
|
beforeEach(function () {
|
||
|
this.result = this.model.update();
|
||
|
this.result = this.model.update({}) || this.result;
|
||
|
});
|
||
|
|
||
|
it('should return false since did not change anything', function () {
|
||
|
expect(this.result).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('should not change anything', function () {
|
||
|
expect(this.widgetChangeSpy).not.toHaveBeenCalled();
|
||
|
expect(this.model.dataviewModel.changedAttributes()).toBe(false);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('when there are some attrsNames but no dataview attrs names defined', function () {
|
||
|
beforeEach(function () {
|
||
|
this.model.set({
|
||
|
attrsNames: ['title']
|
||
|
}, { silent: true });
|
||
|
this.result = this.model.update({
|
||
|
title: 'new title',
|
||
|
column: 'col',
|
||
|
aggregation: 'count',
|
||
|
invalid: 'attr, should not be set'
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should return true since attrs were changed', function () {
|
||
|
expect(this.result).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('should update widget', function () {
|
||
|
expect(this.widgetChangeSpy).toHaveBeenCalled();
|
||
|
});
|
||
|
|
||
|
it('should have changed the valid attrs and leave the rest', function () {
|
||
|
expect(this.model.hasChanged('title')).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('should not change existing attrs', function () {
|
||
|
expect(this.model.hasChanged('collapsed')).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('should not set any invalid attrs', function () {
|
||
|
expect(this.model.get('invalid')).toBeUndefined();
|
||
|
});
|
||
|
|
||
|
it('should not update dataviewModel', function () {
|
||
|
expect(this.model.dataviewModel.changedAttributes()).toBe(false);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('when there are both widget and dataview attrs names defined', function () {
|
||
|
beforeEach(function () {
|
||
|
this.model.set({
|
||
|
attrsNames: ['title']
|
||
|
}, { silent: true });
|
||
|
this.result = this.model.update({
|
||
|
title: 'new title',
|
||
|
column: 'other',
|
||
|
aggregation: 'sum',
|
||
|
foo: 'attr, should not be set'
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should return true since attrs were changed', function () {
|
||
|
expect(this.result).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('should update the widget', function () {
|
||
|
expect(this.model.changedAttributes()).toEqual({
|
||
|
title: 'new title'
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should update the dataview model attrs', function () {
|
||
|
expect(this.model.dataviewModel.changedAttributes()).toEqual({
|
||
|
column: 'other',
|
||
|
aggregation: 'sum'
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('.remove', function () {
|
||
|
beforeEach(function () {
|
||
|
this.removeSpy = jasmine.createSpy('remove');
|
||
|
spyOn(this.model, 'stopListening');
|
||
|
this.model.on('destroy', this.removeSpy);
|
||
|
this.model.remove();
|
||
|
});
|
||
|
|
||
|
it('should remove the model', function () {
|
||
|
expect(this.removeSpy).toHaveBeenCalledWith(this.model);
|
||
|
});
|
||
|
|
||
|
it('should remove dataviewModel', function () {
|
||
|
expect(this.model.dataviewModel.remove).toHaveBeenCalled();
|
||
|
});
|
||
|
|
||
|
it('should call stop listening to events', function () {
|
||
|
expect(this.model.stopListening).toHaveBeenCalled();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('getState', function () {
|
||
|
it('should only return states different from default', function () {
|
||
|
this.model.setState({
|
||
|
collapsed: true
|
||
|
});
|
||
|
expect(this.model.getState()).toEqual({collapsed: true});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('isAutoStyleEnabled', function () {
|
||
|
beforeEach(function () {
|
||
|
this.model.set('type', 'category');
|
||
|
});
|
||
|
|
||
|
it('should return true without style options', function () {
|
||
|
expect(this.model.isAutoStyleEnabled()).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('should return true with empty object style options', function () {
|
||
|
this.model.set('style', {});
|
||
|
expect(this.model.isAutoStyleEnabled()).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('should return true with style options', function () {
|
||
|
var style = {
|
||
|
auto_style: {
|
||
|
allowed: true
|
||
|
}
|
||
|
};
|
||
|
this.model.set('style', style);
|
||
|
expect(this.model.isAutoStyleEnabled()).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('should return false with style options', function () {
|
||
|
var style = {
|
||
|
auto_style: {
|
||
|
allowed: false
|
||
|
}
|
||
|
};
|
||
|
this.model.set('style', style);
|
||
|
expect(this.model.isAutoStyleEnabled()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('should be false if type is not category or histogram', function () {
|
||
|
var model = new WidgetModel(null, {
|
||
|
dataviewModel: dataviewModel,
|
||
|
layerModel: layerModel,
|
||
|
type: 'time-series'
|
||
|
}, {autoStyleEnabled: true});
|
||
|
|
||
|
expect(model.isAutoStyleEnabled()).toBeFalsy();
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('.getAutoStyle', function () {
|
||
|
it('should not provide any info if auto-style is not enabled', function () {
|
||
|
spyOn(this.model, 'isAutoStyleEnabled').and.returnValue(false);
|
||
|
var data = this.model.getAutoStyle();
|
||
|
expect(data).toEqual({});
|
||
|
});
|
||
|
|
||
|
it('should not provide any info if autoStyler is not defined', function () {
|
||
|
spyOn(this.model, 'isAutoStyleEnabled').and.returnValue(true);
|
||
|
this.model.autoStyler = undefined;
|
||
|
var data = this.model.getAutoStyle();
|
||
|
expect(data).toEqual({});
|
||
|
});
|
||
|
|
||
|
it('should return proper definition and cartocss when no style model present', function () {
|
||
|
var definition = 'a definition';
|
||
|
var cartocss = 'some cartocss';
|
||
|
spyOn(this.model, 'isAutoStyleEnabled').and.returnValue(true);
|
||
|
this.model.autoStyler = {
|
||
|
getDef: function () {
|
||
|
return definition;
|
||
|
}
|
||
|
};
|
||
|
layerModel.set('cartocss', cartocss);
|
||
|
var expectedData = {
|
||
|
definition: definition,
|
||
|
cartocss: cartocss
|
||
|
};
|
||
|
|
||
|
var data = this.model.getAutoStyle();
|
||
|
|
||
|
expect(_.isEqual(data, expectedData)).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('should return proper definition and cartocss when auto_style property already present', function () {
|
||
|
var definition = 'a definition';
|
||
|
var cartocss = 'some cartocss';
|
||
|
var style = {
|
||
|
auto_style: {
|
||
|
definition: 'other definition',
|
||
|
cartocss: 'other cartocss',
|
||
|
anotherProperty: 'another property'
|
||
|
}
|
||
|
};
|
||
|
spyOn(this.model, 'isAutoStyleEnabled').and.returnValue(true);
|
||
|
this.model.set('style', style);
|
||
|
this.model.autoStyler = {
|
||
|
getDef: function () {
|
||
|
return definition;
|
||
|
}
|
||
|
};
|
||
|
layerModel.set('cartocss', cartocss);
|
||
|
var expectedData = {
|
||
|
definition: definition,
|
||
|
cartocss: cartocss,
|
||
|
anotherProperty: 'another property'
|
||
|
};
|
||
|
|
||
|
var data = this.model.getAutoStyle();
|
||
|
|
||
|
expect(_.isEqual(data, expectedData)).toBe(true);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('.hasColorsAutoStyle', function () {
|
||
|
it('should return false if autostyle or auto-style definition is empty', function () {
|
||
|
spyOn(this.model, 'getAutoStyle').and.returnValue({
|
||
|
cartocss: '#dummy {}',
|
||
|
definition: {}
|
||
|
});
|
||
|
expect(this.model.hasColorsAutoStyle()).toBe(false);
|
||
|
this.model.getAutoStyle.and.returnValue({});
|
||
|
expect(this.model.hasColorsAutoStyle()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('should return false if color or range doesn\'t exist', function () {
|
||
|
spyOn(this.model, 'getAutoStyle').and.returnValue({
|
||
|
cartocss: '#dummy {}',
|
||
|
definition: {
|
||
|
point: {}
|
||
|
}
|
||
|
});
|
||
|
expect(this.model.hasColorsAutoStyle()).toBe(false);
|
||
|
this.model.getAutoStyle.and.returnValue({
|
||
|
cartocss: '#dummy {}',
|
||
|
definition: {
|
||
|
point: {
|
||
|
color: {}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
expect(this.model.hasColorsAutoStyle()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('should return false if there is no colors defined', function () {
|
||
|
spyOn(this.model, 'getAutoStyle').and.returnValue({
|
||
|
cartocss: '#dummy {}',
|
||
|
definition: {
|
||
|
point: {
|
||
|
color: {
|
||
|
range: []
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
expect(this.model.hasColorsAutoStyle()).toBe(false);
|
||
|
|
||
|
this.model.getAutoStyle.and.returnValue({
|
||
|
cartocss: '#dummy {}',
|
||
|
definition: {
|
||
|
point: {
|
||
|
color: {
|
||
|
range: {}
|
||
|
}
|
||
|
},
|
||
|
line: {
|
||
|
color: {
|
||
|
range: {}
|
||
|
}
|
||
|
},
|
||
|
polygon: {
|
||
|
color: {
|
||
|
range: {}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
expect(this.model.hasColorsAutoStyle()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('should return true if autostyle return any color', function () {
|
||
|
spyOn(this.model, 'getAutoStyle').and.returnValue({
|
||
|
cartocss: '#dummy {}',
|
||
|
definition: {
|
||
|
point: {
|
||
|
color: {
|
||
|
range: ['#red']
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
expect(this.model.hasColorsAutoStyle()).toBe(true);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('.autoStyle', function () {
|
||
|
beforeEach(function () {
|
||
|
spyOn(this.model, 'isAutoStyleEnabled').and.returnValue(true);
|
||
|
this.model.autoStyler = {
|
||
|
getStyle: jasmine.createSpy('getStyle')
|
||
|
};
|
||
|
|
||
|
layerModel.set('initialStyle', 'foo');
|
||
|
layerModel.set('cartocss', 'wadus');
|
||
|
});
|
||
|
|
||
|
it('should generate autostyle styles when dataview has data', function () {
|
||
|
this.model.dataviewModel.set('data', [{
|
||
|
name: 'foo'
|
||
|
}, {
|
||
|
name: 'bar'
|
||
|
}]);
|
||
|
this.model.autoStyle();
|
||
|
|
||
|
expect(this.model.autoStyler.getStyle).toHaveBeenCalled();
|
||
|
expect(layerModel.get('initialStyle')).toBe('wadus');
|
||
|
});
|
||
|
|
||
|
it('should not generate autostyle styles when dataview has data', function () {
|
||
|
this.model.dataviewModel.set('data', []);
|
||
|
this.model.autoStyle();
|
||
|
|
||
|
expect(this.model.autoStyler.getStyle).not.toHaveBeenCalled();
|
||
|
expect(layerModel.get('initialStyle')).toBe('foo');
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('when autostyle option is disabled', function () {
|
||
|
beforeEach(function () {
|
||
|
var vis = specHelper.createDefaultVis();
|
||
|
this.layerModel = vis.map.layers.first();
|
||
|
var source = vis.analysis.findNodeById('a0');
|
||
|
// Use a category dataview as example
|
||
|
this.dataviewModel = vis.dataviews.createCategoryModel({
|
||
|
column: 'col',
|
||
|
source: source
|
||
|
});
|
||
|
this.dataviewModel.remove = spyOn(this.dataviewModel, 'remove');
|
||
|
});
|
||
|
|
||
|
describe('isAutoStyleEnabled', function () {
|
||
|
it('should be true if without autostyle option', function () {
|
||
|
var model = new WidgetModel(null, {
|
||
|
dataviewModel: this.dataviewModel,
|
||
|
layerModel: this.layerModel
|
||
|
});
|
||
|
|
||
|
model.set('type', 'category');
|
||
|
|
||
|
expect(model.isAutoStyleEnabled()).toBe(true);
|
||
|
});
|
||
|
|
||
|
it('should be false if passed autostyle option as false', function () {
|
||
|
var model = new WidgetModel(null, {
|
||
|
dataviewModel: this.dataviewModel,
|
||
|
layerModel: this.layerModel
|
||
|
}, {autoStyleEnabled: false});
|
||
|
|
||
|
model.set('type', 'category');
|
||
|
|
||
|
expect(model.isAutoStyleEnabled()).toBe(false);
|
||
|
});
|
||
|
|
||
|
it('should be true if passed autostyle option as true', function () {
|
||
|
var model = new WidgetModel(null, {
|
||
|
dataviewModel: this.dataviewModel,
|
||
|
layerModel: this.layerModel
|
||
|
}, {autoStyleEnabled: true});
|
||
|
|
||
|
model.set('type', 'category');
|
||
|
|
||
|
expect(model.isAutoStyleEnabled()).toBe(true);
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('.getWidgetColor', function () {
|
||
|
beforeEach(function () {
|
||
|
var vis = specHelper.createDefaultVis();
|
||
|
this.layerModel = vis.map.layers.first();
|
||
|
var source = vis.analysis.findNodeById('a0');
|
||
|
// Use a category dataview as example
|
||
|
this.dataviewModel = vis.dataviews.createCategoryModel({
|
||
|
column: 'col',
|
||
|
source: source
|
||
|
});
|
||
|
|
||
|
this.model = new WidgetModel(null, {
|
||
|
dataviewModel: this.dataviewModel,
|
||
|
layerModel: this.layerModel
|
||
|
}, {autoStyleEnabled: false});
|
||
|
});
|
||
|
|
||
|
describe('when widget_color_changed is true', function () {
|
||
|
it('should return color', function () {
|
||
|
var style = {
|
||
|
widget_style: {
|
||
|
definition: {
|
||
|
color: {
|
||
|
fixed: '#fabada'
|
||
|
}
|
||
|
},
|
||
|
widget_color_changed: true
|
||
|
}
|
||
|
};
|
||
|
this.model.set('style', style);
|
||
|
|
||
|
expect(this.model.getWidgetColor()).toBe('#fabada');
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('when widget_color_changed is false', function () {
|
||
|
it('should not return color', function () {
|
||
|
var style = {
|
||
|
widget_style: {
|
||
|
definition: {
|
||
|
color: {
|
||
|
fixed: '#9DE0AD'
|
||
|
}
|
||
|
},
|
||
|
widget_color_changed: false
|
||
|
}
|
||
|
};
|
||
|
this.model.set('style', style);
|
||
|
|
||
|
expect(this.model.getWidgetColor()).toBe(false);
|
||
|
});
|
||
|
|
||
|
describe('and widget color value has changed', function () { // this is the case for existing widgets
|
||
|
it('should return color', function () {
|
||
|
var style = {
|
||
|
widget_style: {
|
||
|
definition: {
|
||
|
color: {
|
||
|
fixed: '#fabada',
|
||
|
opacity: 1
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
this.model.set('style', style);
|
||
|
|
||
|
expect(this.model.getWidgetColor()).toBe('#fabada');
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
|
||
|
describe('forceResize', function () {
|
||
|
beforeEach(function () {
|
||
|
this.model = new WidgetModel(null, {
|
||
|
dataviewModel: new Backbone.Model(),
|
||
|
layerModel: new Backbone.Model()
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should trigger forceResize event if it is a time-series', function () {
|
||
|
spyOn(this.model, 'trigger');
|
||
|
this.model.set('type', 'time-series');
|
||
|
this.model.forceResize();
|
||
|
|
||
|
expect(this.model.trigger).toHaveBeenCalledWith('forceResize');
|
||
|
});
|
||
|
|
||
|
it('should not trigger force Resize event if it is not a time-series', function () {
|
||
|
spyOn(this.model, 'trigger');
|
||
|
this.model.set('type', 'category');
|
||
|
this.model.forceResize();
|
||
|
|
||
|
expect(this.model.trigger).not.toHaveBeenCalledWith('forceResize');
|
||
|
});
|
||
|
});
|
||
|
});
|