carto.js/test/spec/geo/map-view.spec.js
2020-06-13 18:34:34 +08:00

258 lines
11 KiB
JavaScript

var $ = require('jquery');
var Backbone = require('backbone');
var createEngine = require('../fixtures/engine.fixture.js');
var Map = require('../../../src/geo/map');
var MapView = require('../../../src/geo/map-view');
var TileLayer = require('../../../src/geo/map/tile-layer');
var CartoDBLayer = require('../../../src/geo/map/cartodb-layer');
var CartoDBLayerGroup = require('../../../src/geo/cartodb-layer-group');
var LayerGroupModel = CartoDBLayerGroup;
var fakeLayerViewFactory = {
createLayerView: function () {
var layerView = new Backbone.View();
layerView.setCursor = jasmine.createSpy('setCursor');
spyOn(layerView, 'remove');
return layerView;
}
};
var MyMapView = MapView.extend({
getSize: function () { return { x: 1000, y: 1000 }; },
_getLayerViewFactory: function () {
return fakeLayerViewFactory;
},
_createNativeMap: function () {}
});
describe('core/geo/map-view', function () {
var engineMock;
beforeEach(function () {
this.container = $('<div>').css('height', '200px');
engineMock = createEngine();
this.map = new Map(null, {
layersFactory: {}
});
this.layerViewFactory = jasmine.createSpyObj('layerViewFactory', ['createLayerView']);
this.mapView = new MyMapView({
el: this.container,
mapModel: this.map,
engine: new Backbone.Model(),
layerGroupModel: new LayerGroupModel(null, {
layersCollection: this.map.layers
})
});
spyOn(this.mapView, 'setCursor');
spyOn(this.mapView, 'getNativeMap');
spyOn(this.mapView, '_addLayerToMap');
});
describe('.render', function () {
it('should add layer views to the map', function () {
var tileLayer = new TileLayer(null, { engine: {} });
var cartoDBLayer1 = new CartoDBLayer({}, { engine: engineMock });
var cartoDBLayer2 = new CartoDBLayer({}, { engine: engineMock });
this.map.layers.reset([tileLayer, cartoDBLayer1, cartoDBLayer2]);
this.mapView = new MyMapView({
el: this.container,
mapModel: this.map,
engine: new Backbone.Model(),
layerGroupModel: new LayerGroupModel(null, {
windshaftMap: this.windshaftMap,
layersCollection: this.map.layers
})
});
spyOn(this.mapView, 'getNativeMap');
spyOn(this.mapView, '_addLayerToMap');
this.mapView.render();
expect(this.mapView._addLayerToMap.calls.count()).toEqual(2);
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid)).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(tileLayer.cid)).toBeDefined();
// Both CartoDBLayer layers share the same layer view
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid));
// Tile Layer has a different layer view
expect(this.mapView.getLayerViewByLayerCid(tileLayer.cid)).not.toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid));
});
});
describe('bindings to map', function () {
it('should fitBounds when view bounds change', function () {
spyOn(this.map, 'fitBounds');
this.map.setBounds([ [0, 0], [180, 180] ]);
expect(this.map.fitBounds).toHaveBeenCalled();
});
});
describe('bindings to map.layers', function () {
describe('when layers of map.layers are resetted', function () {
it('should group CartoDB layers into a single layerView and add one layerView for each non-CartoDB layer', function () {
var tileLayer = new TileLayer(null, { engine: {} });
var cartoDBLayer1 = new CartoDBLayer({}, { engine: engineMock });
var cartoDBLayer2 = new CartoDBLayer({}, { engine: engineMock });
this.map.layers.reset([tileLayer, cartoDBLayer1, cartoDBLayer2]);
expect(this.mapView._addLayerToMap.calls.count()).toEqual(2);
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid)).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(tileLayer.cid)).toBeDefined();
// Both CartoDBLayer layers share the same layer view
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid));
// Tile Layer has a different layer view
expect(this.mapView.getLayerViewByLayerCid(tileLayer.cid)).not.toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid));
});
it('should trigger a "newLayerView" event for each new layerView', function () {
var callback = jasmine.createSpy('callback');
this.mapView.on('newLayerView', callback);
var tileLayer = new TileLayer(null, { engine: {} });
var cartoDBLayer1 = new CartoDBLayer({}, { engine: engineMock });
var cartoDBLayer2 = new CartoDBLayer({}, { engine: engineMock });
this.map.layers.reset([tileLayer, cartoDBLayer1, cartoDBLayer2]);
expect(callback.calls.count()).toEqual(2);
expect(callback.calls.argsFor(0)[0]).toEqual(this.mapView.getLayerViewByLayerCid(tileLayer.cid));
expect(callback.calls.argsFor(1)[0]).toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid));
});
});
describe('when new layerModels are added to map.layers', function () {
it('should add a new layer view to the map', function () {
var layer1 = new CartoDBLayer({}, { engine: engineMock });
this.map.addLayer(layer1);
var layerViewForLayer1 = this.mapView.getLayerViewByLayerCid(layer1.cid);
expect(layerViewForLayer1).toBeDefined();
expect(Object.keys(this.mapView._layerViews).length).toEqual(1);
expect(this.mapView._addLayerToMap).toHaveBeenCalled();
});
it('should group CartoDB layers into a single layerView', function () {
var tileLayer = new TileLayer(null, { engine: {} });
var cartoDBLayer1 = new CartoDBLayer({}, { engine: engineMock });
var cartoDBLayer2 = new CartoDBLayer({}, { engine: engineMock });
this.map.addLayer(tileLayer);
expect(this.mapView._addLayerToMap).toHaveBeenCalled();
this.mapView._addLayerToMap.calls.reset();
this.map.addLayer(cartoDBLayer1);
expect(this.mapView._addLayerToMap).toHaveBeenCalled();
this.mapView._addLayerToMap.calls.reset();
this.map.addLayer(cartoDBLayer2);
expect(this.mapView._addLayerToMap).not.toHaveBeenCalled();
// There are only two layerViews cause the CartoDBLayers have been grouped
expect(Object.keys(this.mapView._layerViews).length).toEqual(3);
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid)).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(tileLayer.cid)).toBeDefined();
// Both CartoDBLayer layers share the same layer view
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid));
// Tile Layer has a different layer view
expect(this.mapView.getLayerViewByLayerCid(tileLayer.cid)).not.toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid));
});
it('should trigger a "newLayerView" event for each new layerView', function () {
var callback = jasmine.createSpy('callback');
this.mapView.on('newLayerView', callback);
var tileLayer = new TileLayer(null, { engine: {} });
var cartoDBLayer1 = new CartoDBLayer({}, { engine: engineMock });
var cartoDBLayer2 = new CartoDBLayer({}, { engine: engineMock });
this.map.addLayer(tileLayer);
this.map.addLayer(cartoDBLayer1);
this.map.addLayer(cartoDBLayer2);
expect(callback.calls.count()).toEqual(2);
expect(callback.calls.argsFor(0)[0]).toEqual(this.mapView.getLayerViewByLayerCid(tileLayer.cid));
expect(callback.calls.argsFor(1)[0]).toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid));
});
});
describe('when layerModels are removed from map.layers', function () {
it('should should remove the corresponding layerView for layers that are rendered individually (not grouped)', function () {
var tileLayer = new TileLayer(null, { engine: {} });
this.map.layers.reset([tileLayer]);
var tileLayerView = this.mapView.getLayerViewByLayerCid(tileLayer.cid);
expect(tileLayerView).toBeDefined();
this.map.layers.remove(tileLayer);
// View for the tileLayer has been removed
expect(tileLayerView.remove).toHaveBeenCalled();
expect(this.mapView.getLayerViewByLayerCid(tileLayer.cid)).not.toBeDefined();
});
it('should should only remove a group layerView when all grouped layerModels have been removed', function () {
var cartoDBLayer1 = new CartoDBLayer({}, { engine: engineMock });
var cartoDBLayer2 = new CartoDBLayer({}, { engine: engineMock });
this.map.layers.reset([cartoDBLayer1, cartoDBLayer2]);
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid)).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).toEqual(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid));
var cartoDBLayerGroupView = this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid);
this.map.layers.remove(cartoDBLayer1);
// There's one more CartoDBLayer so the layer view has not been removed
// this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)
expect(cartoDBLayerGroupView.remove).not.toHaveBeenCalled();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer1.cid)).not.toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid)).toBeDefined();
this.map.layers.remove(cartoDBLayer2);
// There's one more CartoDBLayer so the layer view has not been removed
expect(cartoDBLayerGroupView.remove).toHaveBeenCalled();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer2.cid)).not.toBeDefined();
});
it('should be able to add a layer after removing it', function () {
var cartoDBLayer = new CartoDBLayer({}, { engine: engineMock });
this.map.layers.reset([cartoDBLayer]);
var cartodbLayerView = this.mapView.getLayerViewByLayerCid(cartoDBLayer.cid);
expect(cartodbLayerView).toBeDefined();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer.cid)).toBeDefined();
// Remove the layer
this.map.layers.remove(cartoDBLayer);
// View for the cartodbLayer has been removed
expect(cartodbLayerView.remove).toHaveBeenCalled();
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer.cid)).not.toBeDefined();
this.map.layers.add(cartoDBLayer);
expect(this.mapView.getLayerViewByLayerCid(cartoDBLayer.cid)).toBeDefined();
});
});
});
});