Initial commit
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
var DataviewsCollection = require('../../../src/dataviews/dataviews-collection');
|
||||
var DataviewModel = require('../../../src/dataviews/dataview-model-base');
|
||||
var whenAllDataviewsFetched = require('../../../src/vis/dataviews-tracker');
|
||||
var MockFactory = require('../../helpers/mockFactory');
|
||||
|
||||
describe('src/vis/dataviews-tracker', function () {
|
||||
var options = {
|
||||
map: {},
|
||||
engine: {}
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
this.dataviewsFetched = jasmine.createSpy('dataviewsFetched');
|
||||
|
||||
this.source = MockFactory.createAnalysisModel({ id: 'a1' });
|
||||
|
||||
this.onDataviewsfetched = jasmine.createSpy('onDataviewsfetched');
|
||||
|
||||
this.dataviewsCollection = new DataviewsCollection([]);
|
||||
|
||||
whenAllDataviewsFetched(this.dataviewsCollection, this.onDataviewsfetched);
|
||||
});
|
||||
|
||||
it('should check fetchStatus when any dataviews changes', function () {
|
||||
var dataview1 = new DataviewModel({
|
||||
source: this.source
|
||||
}, options);
|
||||
this.dataviewsCollection.add(dataview1);
|
||||
|
||||
var dataview2 = new DataviewModel({
|
||||
source: this.source
|
||||
}, options);
|
||||
this.dataviewsCollection.add(dataview2);
|
||||
|
||||
this.onDataviewsfetched.calls.reset();
|
||||
|
||||
dataview1.set('status', 'fetched');
|
||||
expect(this.onDataviewsfetched).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trigger dataviewsFetched event when all dataviews fetches', function () {
|
||||
var dataview1 = new DataviewModel({
|
||||
source: this.source
|
||||
}, options);
|
||||
this.dataviewsCollection.add(dataview1);
|
||||
|
||||
var dataview2 = new DataviewModel({
|
||||
source: this.source
|
||||
}, options);
|
||||
this.dataviewsCollection.add(dataview2);
|
||||
|
||||
this.onDataviewsfetched.calls.reset();
|
||||
|
||||
dataview1.set('status', 'fetched');
|
||||
dataview2.set('status', 'fetched');
|
||||
|
||||
expect(this.onDataviewsfetched).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,578 @@
|
||||
var Backbone = require('backbone');
|
||||
var Map = require('../../../src/geo/map');
|
||||
var Engine = require('../../../src/engine');
|
||||
var CartoDBLayer = require('../../../src/geo/map/cartodb-layer');
|
||||
var CartoDBLayerGroup = require('../../../src/geo/cartodb-layer-group');
|
||||
var TooltipModel = require('../../../src/geo/ui/tooltip-model');
|
||||
var InfowindowModel = require('../../../src/geo/ui/infowindow-model');
|
||||
var InfowindowManager = require('../../../src/vis/infowindow-manager');
|
||||
var createEngine = require('../fixtures/engine.fixture.js');
|
||||
|
||||
var createCartoDBLayer = function (engine, infowindowAttrs) {
|
||||
infowindowAttrs = infowindowAttrs || {
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
template: '<p>{{ name }}</p>'
|
||||
};
|
||||
return new CartoDBLayer({
|
||||
infowindow: infowindowAttrs
|
||||
}, { engine: engine });
|
||||
};
|
||||
|
||||
var simulateFeatureClickEvent = function (layerView, data) {
|
||||
layerView.trigger('featureClick', {
|
||||
layer: layerView.model.getLayerInLayerGroupAt(data.layerIndex),
|
||||
layerIndex: data.layerIndex,
|
||||
latlng: [100, 200],
|
||||
position: { x: 20, y: 30 },
|
||||
feature: data.data
|
||||
});
|
||||
};
|
||||
|
||||
describe('src/vis/infowindow-manager.js', function () {
|
||||
var engineMock;
|
||||
|
||||
beforeEach(function () {
|
||||
this.map = new Map({}, {
|
||||
layersFactory: {}
|
||||
});
|
||||
|
||||
this.infowindowModel = new InfowindowModel();
|
||||
this.tooltipModel = new TooltipModel();
|
||||
|
||||
this.cartoDBLayerGroup = new CartoDBLayerGroup({}, {
|
||||
layersCollection: this.map.layers
|
||||
});
|
||||
|
||||
this.layerView = new Backbone.View({
|
||||
model: this.cartoDBLayerGroup
|
||||
});
|
||||
|
||||
spyOn(this.cartoDBLayerGroup, 'fetchAttributes').and.callFake(function (layerIndex, featureId, callback) {
|
||||
var data = { name: 'juan' };
|
||||
callback(data);
|
||||
});
|
||||
|
||||
engineMock = createEngine();
|
||||
|
||||
this.infowindowManager = new InfowindowManager({ // eslint-disable-line
|
||||
engine: engineMock,
|
||||
mapModel: this.map,
|
||||
infowindowModel: this.infowindowModel,
|
||||
tooltipModel: this.tooltipModel
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly bind the featureClick event to the corresponding layerView', function () {
|
||||
var layer1 = createCartoDBLayer(engineMock, {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
});
|
||||
|
||||
var layer2 = createCartoDBLayer(engineMock, {
|
||||
template: 'template2',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'description',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names2'
|
||||
});
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1, layer2 ]);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
// A request to fetch the attributes for the right cartodb_id and layerIndex has been triggered
|
||||
expect(this.layerView.model.fetchAttributes.calls.count()).toEqual(1);
|
||||
expect(this.layerView.model.fetchAttributes).toHaveBeenCalledWith(0, 10, jasmine.any(Function));
|
||||
this.layerView.model.fetchAttributes.calls.reset();
|
||||
|
||||
// InfowindowModel has been updated
|
||||
expect(this.infowindowModel.attributes).toEqual({
|
||||
'template': 'template1',
|
||||
'alternative_names': 'alternative_names1',
|
||||
'template_type': 'underscore',
|
||||
'offset': [
|
||||
28,
|
||||
0
|
||||
],
|
||||
'maxHeight': 180,
|
||||
'autoPan': true,
|
||||
'content': {
|
||||
'fields': [
|
||||
{
|
||||
'name': 'name',
|
||||
'title': 'name',
|
||||
'value': 'juan',
|
||||
'index': 0
|
||||
}
|
||||
],
|
||||
'data': {
|
||||
'name': 'juan'
|
||||
}
|
||||
},
|
||||
'latlng': [
|
||||
100,
|
||||
200
|
||||
],
|
||||
'visibility': true,
|
||||
'currentFeatureId': 10
|
||||
});
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 1,
|
||||
data: { cartodb_id: 100 }
|
||||
});
|
||||
|
||||
// A request to fetch the attributes for the right cartodb_id and layerIndex has been triggered
|
||||
expect(this.layerView.model.fetchAttributes.calls.count()).toEqual(1);
|
||||
expect(this.layerView.model.fetchAttributes).toHaveBeenCalledWith(1, 100, jasmine.any(Function));
|
||||
this.layerView.model.fetchAttributes.calls.reset();
|
||||
|
||||
// InfowindowModel has been updated
|
||||
expect(this.infowindowModel.attributes).toEqual({
|
||||
'template': 'template2',
|
||||
'alternative_names': 'alternative_names2',
|
||||
'template_type': 'underscore',
|
||||
'offset': [
|
||||
28,
|
||||
0
|
||||
],
|
||||
'maxHeight': 180,
|
||||
'autoPan': true,
|
||||
'content': {
|
||||
'fields': [
|
||||
{
|
||||
'title': null,
|
||||
'value': 'No data available',
|
||||
'index': 0,
|
||||
'type': 'empty'
|
||||
}
|
||||
],
|
||||
'data': {
|
||||
'name': 'juan'
|
||||
}
|
||||
},
|
||||
'latlng': [
|
||||
100,
|
||||
200
|
||||
],
|
||||
'visibility': true,
|
||||
'currentFeatureId': 100
|
||||
});
|
||||
});
|
||||
|
||||
it('should not fetch attributes and show the infowindow if template is empty', function () {
|
||||
var layer1 = createCartoDBLayer(engineMock, {
|
||||
template: '',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
});
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.layerView.model.fetchAttributes).not.toHaveBeenCalled();
|
||||
expect(this.infowindowModel.get('visibility')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should not fetch attributes and show the infowindow if popups are disabled', function () {
|
||||
var layer1 = createCartoDBLayer(engineMock, {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
});
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
this.map.disablePopups();
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.layerView.model.fetchAttributes).not.toHaveBeenCalled();
|
||||
expect(this.infowindowModel.get('visibility')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should hide the infowindow if map popups are disabled', function () {
|
||||
var layer1 = createCartoDBLayer(engineMock, {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
});
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.infowindowModel.get('visibility')).toEqual(true);
|
||||
|
||||
// Disable Map Popups
|
||||
this.map.disablePopups();
|
||||
|
||||
expect(this.infowindowModel.get('visibility')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should set loading content while loading', function () {
|
||||
var layer1 = createCartoDBLayer(engineMock);
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
|
||||
// Fetch attributes does NOT suceed inmediatily
|
||||
this.layerView.model.fetchAttributes.and.callFake(function () {});
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
// InfowindowModel has been updated
|
||||
expect(this.infowindowModel.get('content').fields).toEqual([
|
||||
{
|
||||
'type': 'loading',
|
||||
'title': 'loading',
|
||||
'value': '…'
|
||||
}
|
||||
]);
|
||||
expect(this.infowindowModel.get('visibility')).toBe(true);
|
||||
});
|
||||
|
||||
it('should set error content if no attributes are returned', function () {
|
||||
var layer1 = new CartoDBLayer({
|
||||
infowindow: {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
|
||||
this.layerView.model.fetchAttributes.and.callFake(function (layerIndex, featureId, callback) {
|
||||
callback();
|
||||
});
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
// InfowindowModel has been updated
|
||||
expect(this.infowindowModel.get('content').fields).toEqual([
|
||||
{
|
||||
'title': null,
|
||||
'alternative_name': null,
|
||||
'value': 'There has been an error...',
|
||||
'index': null,
|
||||
'type': 'error'
|
||||
}
|
||||
]);
|
||||
expect(this.infowindowModel.get('visibility')).toBe(true);
|
||||
});
|
||||
|
||||
it('should set the currentFeatureId on the model when the infowindow is shown', function () {
|
||||
var layer = new CartoDBLayer({
|
||||
infowindow: {
|
||||
template: 'template',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer ]);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.infowindowModel.getCurrentFeatureId()).toEqual(10);
|
||||
});
|
||||
|
||||
it('should hide the tooltip', function () {
|
||||
var layer = new CartoDBLayer({
|
||||
infowindow: {
|
||||
template: 'template',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer ]);
|
||||
|
||||
this.tooltipModel.set('visible', true);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should unset the currentFeatureId on the model when the infowindow is hidden', function () {
|
||||
var layer = createCartoDBLayer(engineMock);
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer ]);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
// Layer is hidden and infowindow too
|
||||
layer.hide();
|
||||
|
||||
expect(this.infowindowModel.getCurrentFeatureId()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should update the infowindow model when the infowindow template gets new fields', function () {
|
||||
var layer = createCartoDBLayer(engineMock);
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer ]);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
spyOn(this.infowindowModel, 'setInfowindowTemplate');
|
||||
|
||||
layer.infowindow.update({
|
||||
fields: [
|
||||
{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
},
|
||||
{
|
||||
'name': 'description',
|
||||
'title': true,
|
||||
'position': 2
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
expect(this.infowindowModel.setInfowindowTemplate).toHaveBeenCalledWith(layer.infowindow);
|
||||
});
|
||||
|
||||
xit('should re-fetch attributes when the vis is reloaded', function () {
|
||||
var layer = createCartoDBLayer(engineMock);
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer ]);
|
||||
|
||||
this.cartoDBLayerGroup.fetchAttributes.and.callFake(function (layerIndex, featureId, callback) {
|
||||
var data = { name: 'juan' };
|
||||
callback(data);
|
||||
});
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.infowindowModel.get('content')).toEqual({
|
||||
'fields': [
|
||||
{
|
||||
'name': 'name',
|
||||
'title': 'name',
|
||||
'value': 'juan',
|
||||
'index': 0
|
||||
}
|
||||
],
|
||||
'data': {
|
||||
'name': 'juan'
|
||||
}
|
||||
});
|
||||
|
||||
this.cartoDBLayerGroup.fetchAttributes.and.callFake(function (layerIndex, featureId, callback) {
|
||||
var data = { name: 'luis' };
|
||||
callback(data);
|
||||
});
|
||||
|
||||
engineMock._eventEmmitter.trigger(Engine.Events.RELOAD_SUCCESS);
|
||||
|
||||
// InfowindowModel has been updated
|
||||
expect(this.infowindowModel.get('content')).toEqual({
|
||||
'fields': [
|
||||
{
|
||||
'name': 'name',
|
||||
'title': 'name',
|
||||
'value': 'luis',
|
||||
'index': 0
|
||||
}
|
||||
],
|
||||
'data': {
|
||||
'name': 'luis'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should hide the infowindow when fields are cleared in the infowindow template', function () {
|
||||
// Simulate that the layerView has been added a tooltipView
|
||||
var tooltipView = jasmine.createSpyObj('tooltipView', ['setFilter', 'hide']);
|
||||
tooltipView.setFilter.and.returnValue(tooltipView);
|
||||
this.layerView.tooltipView = tooltipView;
|
||||
|
||||
var layer1 = createCartoDBLayer(engineMock);
|
||||
var layer2 = createCartoDBLayer(engineMock);
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1, layer2 ]);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.infowindowModel.get('visibility')).toBe(true);
|
||||
|
||||
// Clear fields on layer #1
|
||||
layer2.infowindow.update({
|
||||
fields: []
|
||||
});
|
||||
|
||||
// Nothing happened
|
||||
expect(this.infowindowModel.get('visibility')).toBe(true);
|
||||
expect(engineMock.reload).not.toHaveBeenCalledWith({});
|
||||
|
||||
// Clear fields on layer #0 (the one that was opened)
|
||||
layer1.infowindow.update({
|
||||
fields: []
|
||||
});
|
||||
|
||||
// Infowindow has been closed and map has NOT been reloaded
|
||||
expect(this.infowindowModel.get('visibility')).toBe(false);
|
||||
expect(engineMock.reload).not.toHaveBeenCalledWith({});
|
||||
});
|
||||
|
||||
it('should hide the infowindow if the layer is hidden', function () {
|
||||
var layer1 = createCartoDBLayer(engineMock);
|
||||
var layer2 = createCartoDBLayer(engineMock);
|
||||
|
||||
this.infowindowManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1, layer2 ]);
|
||||
|
||||
simulateFeatureClickEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.infowindowModel.get('visibility')).toBe(true);
|
||||
|
||||
// hide layer2 -> nothing happens
|
||||
layer2.hide();
|
||||
|
||||
expect(this.infowindowModel.get('visibility')).toBe(true);
|
||||
|
||||
// hide layer1 -> infowindow is hidden
|
||||
layer1.hide();
|
||||
|
||||
expect(this.infowindowModel.get('visibility')).toBe(false);
|
||||
});
|
||||
|
||||
describe('.fetchAttributes', function () {
|
||||
it('should work as expected?', function () {
|
||||
jasmine.clock().install();
|
||||
var currentCall = 0;
|
||||
spyOn(this.infowindowModel, 'updateContent');
|
||||
this.infowindowManager._cartoDBLayerGroupView = this.layerView;
|
||||
this.currentFeatureId = 10;
|
||||
|
||||
spyOn(this.cartoDBLayerGroup, 'getIndexOfLayerInLayerGroup').and.callFake(function () {
|
||||
return currentCall++;
|
||||
});
|
||||
|
||||
this.cartoDBLayerGroup.fetchAttributes.and.callFake(function (layerIndex, featureId, callback) {
|
||||
var data = { name: 'test' };
|
||||
|
||||
currentCall === 1
|
||||
? setTimeout(function () { callback(data); }, 100)
|
||||
: callback(data);
|
||||
});
|
||||
|
||||
this.infowindowManager._fetchAttributes(10);
|
||||
this.infowindowManager._fetchAttributes(4);
|
||||
|
||||
jasmine.clock().tick(101);
|
||||
expect(this.infowindowModel.updateContent.calls.count()).toEqual(1);
|
||||
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,199 @@
|
||||
var _ = require('underscore');
|
||||
|
||||
var AnalysisModel = require('../../../src/analysis/analysis-model');
|
||||
var LayersFactory = require('../../../src/vis/layers-factory');
|
||||
var createEngine = require('../fixtures/engine.fixture.js');
|
||||
|
||||
var createFakeAnalysis = function (attrs) {
|
||||
return new AnalysisModel(attrs, {
|
||||
engine: {},
|
||||
camshaftReference: {
|
||||
getParamNamesForAnalysisType: function () {}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
describe('vis/layers-factory', function () {
|
||||
var analysis;
|
||||
var layersFactory;
|
||||
var engineMock;
|
||||
|
||||
beforeEach(function () {
|
||||
engineMock = createEngine();
|
||||
|
||||
this.windshaftSettings = {
|
||||
urlTemplate: 'http://{user}.carto.com',
|
||||
userName: 'JUAN',
|
||||
templateName: 'TPL_12345678',
|
||||
client: 'CLIENT_VERSION',
|
||||
apiKey: 'API_KEY',
|
||||
authToken: 'AUTH_TOKEN'
|
||||
};
|
||||
|
||||
layersFactory = new LayersFactory({
|
||||
engine: engineMock,
|
||||
windshaftSettings: this.windshaftSettings
|
||||
});
|
||||
|
||||
analysis = createFakeAnalysis();
|
||||
});
|
||||
|
||||
describe('attribute validation', function () {
|
||||
var testCases = [
|
||||
{
|
||||
layerType: 'CartoDB',
|
||||
// TODO: Once https://github.com/CartoDB/cartodb/issues/12885 is merged
|
||||
// source should be required again so we need to add the attribute to this test
|
||||
// expectedErrorMessage: 'The following attributes are missing: source,cartocss'
|
||||
expectedErrorMessage: 'The following attributes are missing: cartocss'
|
||||
},
|
||||
{
|
||||
layerType: 'torque',
|
||||
// TODO: Once https://github.com/CartoDB/cartodb/issues/12885 is merged
|
||||
// source should be required again so we need to add the attribute to this test
|
||||
// expectedErrorMessage: 'The following attributes are missing: source,cartocss'
|
||||
expectedErrorMessage: 'The following attributes are missing: cartocss'
|
||||
},
|
||||
{
|
||||
layerType: 'Tiled',
|
||||
expectedErrorMessage: 'The following attributes are missing: urlTemplate'
|
||||
},
|
||||
{
|
||||
layerType: 'WMS',
|
||||
expectedErrorMessage: 'The following attributes are missing: urlTemplate'
|
||||
},
|
||||
{
|
||||
layerType: 'GMapsBase',
|
||||
expectedErrorMessage: 'The following attributes are missing: baseType'
|
||||
},
|
||||
{
|
||||
layerType: 'Plain',
|
||||
expectedErrorMessage: 'The following attributes are missing: image|color'
|
||||
}
|
||||
];
|
||||
|
||||
_.each(testCases, function (testCase) {
|
||||
describe(testCase.layerType, function () {
|
||||
it('should throw an error if no properties are given', function () {
|
||||
expect(function () {
|
||||
layersFactory.createLayer(testCase.layerType, {});
|
||||
}).toThrowError(testCase.expectedErrorMessage);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('tiled', function () {
|
||||
it('should create the layer model', function () {
|
||||
var layerModel = layersFactory.createLayer('tiled', {
|
||||
urlTemplate: 'http'
|
||||
});
|
||||
|
||||
expect(layerModel).toBeDefined();
|
||||
expect(layerModel.get('type')).toEqual('Tiled');
|
||||
});
|
||||
|
||||
_.each({
|
||||
'https://dnv9my2eseobd.cloudfront.net/': 'http://a.tiles.mapbox.com/',
|
||||
'https://maps.nlp.nokia.com/': 'http://maps.nlp.nokia.com/',
|
||||
'https://tile.stamen.com/': 'http://tile.stamen.com/',
|
||||
'https://{s}.maps.nlp.nokia.com/': 'http://{s}.maps.nlp.nokia.com/',
|
||||
'https://cartocdn_{s}.global.ssl.fastly.net/': 'http://{s}.api.cartocdn.com/',
|
||||
'https://cartodb-basemaps-{s}.global.ssl.fastly.net/': 'http://{s}.basemaps.cartocdn.com/'
|
||||
}, function (httpUrlTemplate, httpsUrlTemplate) {
|
||||
describe('when https option is set to true', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(LayersFactory, 'isHttps').and.returnValue(true);
|
||||
});
|
||||
|
||||
it("should not convert '" + httpsUrlTemplate + "'", function () {
|
||||
var layerModel = layersFactory.createLayer('tiled', {
|
||||
urlTemplate: httpsUrlTemplate
|
||||
});
|
||||
|
||||
expect(layerModel.get('urlTemplate')).toEqual(httpsUrlTemplate);
|
||||
});
|
||||
|
||||
it("should convert '" + httpUrlTemplate + "' to '" + httpsUrlTemplate + "'", function () {
|
||||
var layerModel = layersFactory.createLayer('tiled', {
|
||||
urlTemplate: httpUrlTemplate
|
||||
});
|
||||
|
||||
expect(layerModel.get('urlTemplate')).toEqual(httpsUrlTemplate);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when https option is set to false', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(LayersFactory, 'isHttps').and.returnValue(false);
|
||||
});
|
||||
|
||||
it("should not convert '" + httpUrlTemplate + "'", function () {
|
||||
var layerModel = layersFactory.createLayer('tiled', {
|
||||
urlTemplate: httpUrlTemplate
|
||||
});
|
||||
|
||||
expect(layerModel.get('urlTemplate')).toEqual(httpUrlTemplate);
|
||||
});
|
||||
|
||||
it("should convert '" + httpsUrlTemplate + "' to '" + httpUrlTemplate + "'", function () {
|
||||
var layerModel = layersFactory.createLayer('tiled', {
|
||||
urlTemplate: httpsUrlTemplate
|
||||
});
|
||||
|
||||
expect(layerModel.get('urlTemplate')).toEqual(httpUrlTemplate);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('torque', function () {
|
||||
it('should create the layer model', function () {
|
||||
var layerModel = layersFactory.createLayer('torque', {
|
||||
source: analysis,
|
||||
cartocss: '#layer {}'
|
||||
});
|
||||
|
||||
expect(layerModel).toBeDefined();
|
||||
expect(layerModel.get('type')).toEqual('torque');
|
||||
});
|
||||
|
||||
it('should setup attrs for windshaft provider', function () {
|
||||
var layerModel = layersFactory.createLayer('torque', {
|
||||
source: analysis,
|
||||
cartocss: '#layer {}'
|
||||
});
|
||||
expect(layerModel.get('user_name')).toEqual('JUAN');
|
||||
expect(layerModel.get('maps_api_template')).toEqual('http://{user}.carto.com');
|
||||
expect(layerModel.get('client')).toEqual('CLIENT_VERSION');
|
||||
expect(layerModel.get('named_map')).toEqual({
|
||||
name: 'TPL_12345678'
|
||||
});
|
||||
expect(layerModel.get('api_key')).toEqual('API_KEY');
|
||||
expect(layerModel.get('auth_token')).toEqual('AUTH_TOKEN');
|
||||
});
|
||||
|
||||
it("should not include a named_map attr if settings don't have one", function () {
|
||||
delete this.windshaftSettings.templateName;
|
||||
|
||||
var layerModel = layersFactory.createLayer('torque', {
|
||||
source: analysis,
|
||||
cartocss: '#layer {}'
|
||||
});
|
||||
expect(layerModel.get('named_map')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
['cartodb', 'torque'].forEach(function (layerType) {
|
||||
describe(layerType + ' (shared)', function () {
|
||||
it('should set accept an AnalysisMode as a source', function () {
|
||||
var layerModel = layersFactory.createLayer(layerType, {
|
||||
source: analysis,
|
||||
cartocss: '#layer {}'
|
||||
});
|
||||
|
||||
expect(layerModel.getSource()).toEqual(analysis);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,146 @@
|
||||
var Backbone = require('backbone');
|
||||
var MapCursorManager = require('../../../src/vis/map-cursor-manager');
|
||||
var CartoDBLayer = require('../../../src/geo/map/cartodb-layer');
|
||||
|
||||
var createLayerModel = function () {
|
||||
var layerModel = new CartoDBLayer(null, { engine: { reload: function () {}, on: function () {} } });
|
||||
layerModel.isInfowindowEnabled = jasmine.createSpy('isInfowindowEnabled');
|
||||
return layerModel;
|
||||
};
|
||||
|
||||
describe('src/vis/map-cursor-manager.js', function () {
|
||||
beforeEach(function () {
|
||||
this.mapView = jasmine.createSpyObj('mapView', ['setCursor']);
|
||||
this.mapModel = jasmine.createSpyObj('map', ['arePopupsEnabled', 'isFeatureInteractivityEnabled']);
|
||||
this.layerModel = createLayerModel();
|
||||
this.cartoDBLayerGroupView = new Backbone.View();
|
||||
this.mapCursorManager = new MapCursorManager({
|
||||
mapView: this.mapView,
|
||||
mapModel: this.mapModel
|
||||
});
|
||||
|
||||
this.mapCursorManager.start(this.cartoDBLayerGroupView);
|
||||
});
|
||||
|
||||
describe('when a feature is overed', function () {
|
||||
beforeEach(function () {
|
||||
this.mapModel.arePopupsEnabled.and.returnValue(false);
|
||||
this.mapModel.isFeatureInteractivityEnabled.and.returnValue(false);
|
||||
this.layerModel.isInfowindowEnabled.and.returnValue(false);
|
||||
});
|
||||
|
||||
it('should NOT change the cursor to pointer if layer is not clickable', function () {
|
||||
this.cartoDBLayerGroupView.trigger('featureOver', {
|
||||
layer: this.layerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should change the cursor to pointer if feature interactivity is enabled', function () {
|
||||
this.mapModel.isFeatureInteractivityEnabled.and.returnValue(true);
|
||||
this.cartoDBLayerGroupView.trigger('featureOver', {
|
||||
layer: this.layerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('pointer');
|
||||
});
|
||||
|
||||
describe('when popups are enabled', function () {
|
||||
beforeEach(function () {
|
||||
this.mapModel.arePopupsEnabled.and.returnValue(true);
|
||||
});
|
||||
|
||||
it('should NOT change the cursor to pointer if layer has NO infowindow enabled', function () {
|
||||
this.cartoDBLayerGroupView.trigger('featureOver', {
|
||||
layer: this.layerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should change the cursor to pointer if layer infowindows enabled', function () {
|
||||
this.layerModel.isInfowindowEnabled.and.returnValue(true);
|
||||
this.cartoDBLayerGroupView.trigger('featureOver', {
|
||||
layer: this.layerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('pointer');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a feature is not overed anymore', function () {
|
||||
beforeEach(function () {
|
||||
this.mapModel.isFeatureInteractivityEnabled.and.returnValue(true);
|
||||
|
||||
this.cartoDBLayerGroupView.trigger('featureOver', {
|
||||
layer: this.layerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('pointer');
|
||||
this.mapView.setCursor.calls.reset();
|
||||
});
|
||||
|
||||
it('should change the cursor to auto if no other layer is being overed', function () {
|
||||
this.cartoDBLayerGroupView.trigger('featureOut', {
|
||||
layer: this.layerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('auto');
|
||||
});
|
||||
|
||||
it('should change the cursor to pointer if other clickable layers are still being overed', function () {
|
||||
var anotherLayerModel = createLayerModel();
|
||||
|
||||
// Another layer is being overed
|
||||
this.cartoDBLayerGroupView.trigger('featureOver', {
|
||||
layer: anotherLayerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('pointer');
|
||||
expect(this.mapView.setCursor.calls.reset());
|
||||
|
||||
// First layer is not overed anymore
|
||||
this.cartoDBLayerGroupView.trigger('featureOut', {
|
||||
layer: this.layerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('pointer');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a feature was overed and layer visibility changes', function () {
|
||||
beforeEach(function () {
|
||||
this.mapModel.isFeatureInteractivityEnabled.and.returnValue(true);
|
||||
this.cartoDBLayerGroupView.trigger('featureOver', {
|
||||
layer: this.layerModel
|
||||
});
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('pointer');
|
||||
});
|
||||
|
||||
it('should change the cursor to auto if layer is hidden', function () {
|
||||
this.mapView.setCursor.calls.reset();
|
||||
|
||||
this.layerModel.set('visible', false);
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('auto');
|
||||
});
|
||||
|
||||
it('should keep the cursor as pointer if layer is hidden but other clickable layers are visible', function () {
|
||||
var anotherLayerModel = createLayerModel();
|
||||
|
||||
// Another layer is being overed
|
||||
this.cartoDBLayerGroupView.trigger('featureOver', {
|
||||
layer: anotherLayerModel
|
||||
});
|
||||
|
||||
this.mapView.setCursor.calls.reset();
|
||||
|
||||
this.layerModel.set('visible', false);
|
||||
|
||||
expect(this.mapView.setCursor).toHaveBeenCalledWith('pointer');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var OverlaysFactory = require('../../../src/vis/overlays-factory');
|
||||
|
||||
describe('vis/overlays-factory', function () {
|
||||
beforeEach(function () {
|
||||
this.map = new Backbone.Model();
|
||||
this.map.layers = new Backbone.Collection();
|
||||
this.map.getMapViewSize = function () {
|
||||
return { x: 650, y: 1000 };
|
||||
};
|
||||
|
||||
this.mapView = new Backbone.View();
|
||||
this.mapView.map = this.map;
|
||||
this.mapView.latLngToContainerPoint = function () {
|
||||
return { x: 100, y: 200 };
|
||||
};
|
||||
|
||||
this.visView = new Backbone.View();
|
||||
this.visView.mapView = this.mapView;
|
||||
|
||||
this.overlaysFactory = new OverlaysFactory({
|
||||
mapModel: this.map,
|
||||
mapView: this.mapView,
|
||||
visView: this.visView
|
||||
});
|
||||
});
|
||||
|
||||
it('should register and create a type', function () {
|
||||
var spy = jasmine.createSpy('spy').and.callFake(function (data, deps) {
|
||||
return {};
|
||||
});
|
||||
OverlaysFactory.register('test', spy);
|
||||
|
||||
var overlay = this.overlaysFactory.create('test', { a: 'something' });
|
||||
expect(spy).toHaveBeenCalledWith({
|
||||
a: 'something',
|
||||
options: {}
|
||||
}, {
|
||||
mapModel: this.map,
|
||||
mapView: this.mapView,
|
||||
visView: this.visView
|
||||
});
|
||||
expect(overlay.type).toEqual('test');
|
||||
});
|
||||
|
||||
_.each([
|
||||
{ type: 'logo', data: {} },
|
||||
{ type: 'attribution', data: {} },
|
||||
{ type: 'zoom', data: {} },
|
||||
{ type: 'loader', data: {} },
|
||||
{ type: 'fullscreen', data: {} },
|
||||
{ type: 'search', data: {} }
|
||||
], function (testCase) {
|
||||
var overlayType = testCase.type;
|
||||
var overlayData = testCase.data;
|
||||
|
||||
it('should create a "' + overlayType + '" overlay', function () {
|
||||
var overlay = this.overlaysFactory.create(overlayType, overlayData);
|
||||
expect(overlay).toBeDefined();
|
||||
});
|
||||
}, this);
|
||||
});
|
||||
@@ -0,0 +1,343 @@
|
||||
var Backbone = require('backbone');
|
||||
var Map = require('../../../src/geo/map');
|
||||
var CartoDBLayer = require('../../../src/geo/map/cartodb-layer');
|
||||
var CartoDBLayerGroup = require('../../../src/geo/cartodb-layer-group');
|
||||
var TooltipModel = require('../../../src/geo/ui/tooltip-model');
|
||||
var InfowindowModel = require('../../../src/geo/ui/infowindow-model');
|
||||
var TooltipManager = require('../../../src/vis/tooltip-manager');
|
||||
var createEngine = require('../fixtures/engine.fixture.js');
|
||||
|
||||
var simulateFeatureOverEvent = function (layerView, data) {
|
||||
layerView.trigger('featureOver', {
|
||||
layer: layerView.model.getLayerInLayerGroupAt(data.layerIndex),
|
||||
layerIndex: data.layerIndex,
|
||||
latlng: [100, 200],
|
||||
position: data.position || { x: 20, y: 30 },
|
||||
feature: data.data
|
||||
});
|
||||
};
|
||||
|
||||
var simulateFeatureOutEvent = function (layerView, data) {
|
||||
layerView.trigger('featureOut', {
|
||||
layer: layerView.model.getLayerInLayerGroupAt(data.layerIndex),
|
||||
layerIndex: data.layerIndex
|
||||
});
|
||||
};
|
||||
|
||||
describe('src/vis/tooltip-manager.js', function () {
|
||||
var engineMock;
|
||||
|
||||
beforeEach(function () {
|
||||
this.map = new Map(null, { layersFactory: {} });
|
||||
this.layerView = new Backbone.View({
|
||||
model: new CartoDBLayerGroup({}, {
|
||||
layersCollection: this.map.layers
|
||||
})
|
||||
});
|
||||
|
||||
engineMock = createEngine();
|
||||
|
||||
this.tooltipModel = new TooltipModel();
|
||||
this.infowindowModel = new InfowindowModel();
|
||||
|
||||
this.tooltipManager = new TooltipManager({ // eslint-disable-line
|
||||
engine: engineMock,
|
||||
mapModel: this.map,
|
||||
tooltipModel: this.tooltipModel,
|
||||
infowindowModel: this.infowindowModel
|
||||
});
|
||||
});
|
||||
|
||||
it('should show the tooltip when a feature is hovered', function () {
|
||||
var layer1 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
var layer2 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template2',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'description',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names2'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.tooltipManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1, layer2 ]);
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
position: { x: 100, y: 200 },
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.get('position')).toEqual({ x: 100, y: 200 });
|
||||
expect(this.tooltipModel.get('fields')).toEqual([{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}]);
|
||||
expect(this.tooltipModel.get('template')).toEqual('template1');
|
||||
expect(this.tooltipModel.get('alternative_names')).toEqual('alternative_names1');
|
||||
expect(this.tooltipModel.isVisible()).toBeTruthy();
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 1,
|
||||
position: { x: 200, y: 300 },
|
||||
data: { cartodb_id: 10 }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.get('position')).toEqual({ x: 200, y: 300 });
|
||||
expect(this.tooltipModel.get('fields')).toEqual([{
|
||||
'name': 'description',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}]);
|
||||
expect(this.tooltipModel.get('template')).toEqual('template2');
|
||||
expect(this.tooltipModel.get('alternative_names')).toEqual('alternative_names2');
|
||||
expect(this.tooltipModel.isVisible()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should NOT show the tooltip when a feature is hovered and infowindow is opened', function () {
|
||||
var layer1 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.tooltipManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeTruthy();
|
||||
|
||||
simulateFeatureOutEvent(this.layerView, {
|
||||
layerIndex: 0
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeFalsy();
|
||||
|
||||
// Infowindow for layer1 is now visible
|
||||
this.infowindowModel.setInfowindowTemplate(layer1.infowindow);
|
||||
this.infowindowModel.setCurrentFeatureId(10);
|
||||
this.infowindowModel.show();
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should hide the tooltip when a feature is not hovered anymore', function () {
|
||||
var layer1 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.tooltipManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeTruthy();
|
||||
|
||||
simulateFeatureOutEvent(this.layerView, {
|
||||
layerIndex: 0
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should hide the tooltip when the layer is hidden', function () {
|
||||
var layer1 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.tooltipManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeTruthy();
|
||||
|
||||
layer1.hide();
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should NOT hide the tooltip when a feature is being featured over and other features are outered', function () {
|
||||
var layer1 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
var layer2 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template2',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.tooltipManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1, layer2 ]);
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeTruthy();
|
||||
|
||||
// A feature from a different layer is not overed anymore
|
||||
simulateFeatureOutEvent(this.layerView, {
|
||||
layerIndex: 1
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should NOT show the tooltip if popups are disabled', function () {
|
||||
var layer1 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template1',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.tooltipManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
this.map.disablePopups();
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
expect(this.tooltipModel.isVisible()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should NOT show the tooltip if tooltip has no template', function () {
|
||||
var layer1 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: '',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'name',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names1'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.tooltipManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1 ]);
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should NOT show the tooltipView if the layerModel doesn\'t have tooltip data', function () {
|
||||
var layer1 = new CartoDBLayer({}, { engine: engineMock });
|
||||
var layer2 = new CartoDBLayer({
|
||||
tooltip: {
|
||||
template: 'template2',
|
||||
template_type: 'underscore',
|
||||
fields: [{
|
||||
'name': 'description',
|
||||
'title': true,
|
||||
'position': 1
|
||||
}],
|
||||
alternative_names: 'alternative_names2'
|
||||
}
|
||||
}, { engine: engineMock });
|
||||
|
||||
this.tooltipManager.start(this.layerView);
|
||||
|
||||
this.map.layers.reset([ layer1, layer2 ]);
|
||||
|
||||
simulateFeatureOverEvent(this.layerView, {
|
||||
layerIndex: 0,
|
||||
data: { cartodb_id: 10, name: 'CARTO' }
|
||||
});
|
||||
|
||||
expect(this.tooltipModel.isVisible()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,140 @@
|
||||
var $ = require('jquery');
|
||||
var Backbone = require('backbone');
|
||||
|
||||
var VisView = require('../../../src/vis/vis-view');
|
||||
var VisModel = require('../../../src/vis/vis');
|
||||
var VizJSON = require('../../../src/api/vizjson');
|
||||
var Engine = require('../../../src/engine');
|
||||
var MapViewFactory = require('../../../src/geo/map-view-factory');
|
||||
|
||||
var createVisView = function (container, visModel, settingsModel) {
|
||||
var options = {
|
||||
el: container,
|
||||
widgets: new Backbone.Collection(),
|
||||
model: visModel,
|
||||
settingsModel: settingsModel
|
||||
};
|
||||
|
||||
return new VisView(options);
|
||||
};
|
||||
|
||||
describe('vis/vis-view', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(MapViewFactory, 'createMapView').and.returnValue(jasmine.createSpyObj('fakeMapView', ['render', 'clean', 'bind']));
|
||||
this.container = $('<div>').css('height', '200px');
|
||||
this.mapConfig = {
|
||||
updated_at: 'cachebuster',
|
||||
title: 'irrelevant',
|
||||
description: 'not so irrelevant',
|
||||
url: 'https://carto.com',
|
||||
center: [40.044, -101.95],
|
||||
zoom: 4,
|
||||
bounds: [
|
||||
[1, 2],
|
||||
[3, 4]
|
||||
],
|
||||
user: {
|
||||
fullname: 'Chuck Norris',
|
||||
avatar_url: 'http://example.com/avatar.jpg'
|
||||
},
|
||||
datasource: {
|
||||
user_name: 'wadus',
|
||||
maps_api_template: 'https://{user}.example.com:443',
|
||||
stat_tag: 'ece6faac-7271-11e5-a85f-04013fc66a01'
|
||||
}
|
||||
};
|
||||
|
||||
this.visModel = new VisModel();
|
||||
this.settingsModel = new Backbone.Model({
|
||||
showLegends: true,
|
||||
showLayerSelector: true
|
||||
});
|
||||
|
||||
this.visView = createVisView(this.container, this.visModel, this.settingsModel);
|
||||
|
||||
this.visModel.load(new VizJSON(this.mapConfig));
|
||||
this.visModel.map.setMapViewSize({ x: 650, y: 1000 });
|
||||
this.visView.render();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
describe('map provider', function () {
|
||||
it('should have created a LeafletMap by default', function () {
|
||||
expect(MapViewFactory.createMapView.calls.mostRecent().args[0]).toEqual('leaflet');
|
||||
});
|
||||
|
||||
it('should have created a LeafletMap when map provider is "leaflet"', function () {
|
||||
this.visModel.map.set('provider', 'leaflet');
|
||||
expect(MapViewFactory.createMapView).toHaveBeenCalledWith('leaflet', jasmine.anything());
|
||||
});
|
||||
|
||||
it('should have created a GoogleMap when map provider is "google"', function () {
|
||||
this.visModel.map.set('provider', 'googlemaps');
|
||||
expect(MapViewFactory.createMapView).toHaveBeenCalledWith('googlemaps', jasmine.anything());
|
||||
});
|
||||
});
|
||||
|
||||
var INVALIDATE_SIZE_WAIT_IN_MS = 160;
|
||||
|
||||
it('should center map to origin once when map height is 0 initially and window is resized', function () {
|
||||
jasmine.clock().install();
|
||||
spyOn(this.visModel, 'invalidateSize');
|
||||
|
||||
var container = $('<div>').css('height', '0');
|
||||
this.visView = createVisView(container, this.visModel, this.settingsModel);
|
||||
|
||||
this.visView.render();
|
||||
|
||||
// First time the window is resized -> map is centered to origin
|
||||
$(window).trigger('resize');
|
||||
|
||||
jasmine.clock().tick(INVALIDATE_SIZE_WAIT_IN_MS);
|
||||
|
||||
expect(this.visModel.invalidateSize).toHaveBeenCalled();
|
||||
|
||||
this.visModel.invalidateSize.calls.reset();
|
||||
|
||||
// Second time the window is resized -> map is NOT centered to origin
|
||||
|
||||
$(window).trigger('resize');
|
||||
|
||||
jasmine.clock().tick(INVALIDATE_SIZE_WAIT_IN_MS);
|
||||
|
||||
expect(this.visModel.invalidateSize).not.toHaveBeenCalled();
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
|
||||
it('should NOT center map to origin when map height is greated than O initially and window is resized', function () {
|
||||
jasmine.clock().install();
|
||||
spyOn(this.visModel, 'invalidateSize');
|
||||
|
||||
var container = $('<div>').css('height', '800px');
|
||||
this.visView = createVisView(container, this.visModel, this.settingsModel);
|
||||
|
||||
this.visView.render();
|
||||
|
||||
// Window is resized by map is not centered since height hasn't changed
|
||||
$(window).trigger('resize');
|
||||
|
||||
jasmine.clock().tick(INVALIDATE_SIZE_WAIT_IN_MS);
|
||||
|
||||
expect(this.visModel.invalidateSize).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should display/hide the loader while loading', function () {
|
||||
this.visModel.overlaysCollection.add({ type: 'loader' });
|
||||
|
||||
expect(this.visView.$el.find('.CDB-Loader:not(.is-visible)').length).toEqual(1);
|
||||
|
||||
this.visModel._engine._eventEmmitter.trigger(Engine.Events.RELOAD_STARTED);
|
||||
|
||||
expect(this.visView.$el.find('.CDB-Loader.is-visible').length).toEqual(1);
|
||||
|
||||
this.visModel._engine._eventEmmitter.trigger(Engine.Events.RELOAD_SUCCESS);
|
||||
|
||||
expect(this.visView.$el.find('.CDB-Loader:not(.is-visible)').length).toEqual(1);
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user