describe('refreshClusters', function () { ///////////////////////////// // SETUP FOR EACH TEST ///////////////////////////// var clock, div, map, group; beforeEach(function () { clock = sinon.useFakeTimers(); div = document.createElement('div'); div.style.width = '200px'; div.style.height = '200px'; document.body.appendChild(div); map = L.map(div, { maxZoom: 18, trackResize: false }); // Corresponds to zoom level 8 for the above div dimensions. map.fitBounds(new L.LatLngBounds([ [1, 1], [2, 2] ])); }); afterEach(function () { if (group instanceof L.MarkerClusterGroup) { group.clearLayers(); map.removeLayer(group); } map.remove(); div.remove() clock.restore(); clock = div = map = group = null; }); function getClusterAtZoom(marker, zoom) { var parent = marker.__parent; while (parent && parent._zoom !== zoom) { parent = parent.__parent; } return parent; } function setMapView() { // Now look at the markers to force cluster icons drawing. // Corresponds to zoom level 8 for the above div dimensions. map.fitBounds(new L.LatLngBounds([ [1, 1], [2, 2] ])); } ///////////////////////////// // TESTS ///////////////////////////// it('flags all non-visible parent clusters of a given marker', function () { group = L.markerClusterGroup().addTo(map); var marker1 = L.marker([1.5, 1.5]).addTo(group), marker2 = L.marker([1.5, 1.5]).addTo(group); // Needed to force a cluster. setMapView(); var marker1cluster10 = getClusterAtZoom(marker1, 10), marker1cluster2 = getClusterAtZoom(marker1, 2), marker1cluster5 = getClusterAtZoom(marker1, 5); // First go to some zoom levels so that Leaflet initializes clusters icons. expect(marker1cluster10._iconNeedsUpdate).to.be.ok(); map.setZoom(10, {animate: false}); expect(marker1cluster10._iconNeedsUpdate).to.not.be.ok(); expect(marker1cluster2._iconNeedsUpdate).to.be.ok(); map.setZoom(2, {animate: false}); expect(marker1cluster2._iconNeedsUpdate).to.not.be.ok(); // Finish on an intermediate zoom level. expect(marker1cluster5._iconNeedsUpdate).to.be.ok(); map.setZoom(5, {animate: false}); expect(marker1cluster5._iconNeedsUpdate).to.not.be.ok(); // Run any animation. clock.tick(1000); // Then request clusters refresh. // No need to actually modify the marker. group.refreshClusters(marker1); // Now check that non-visible clusters are flagged as "dirty". expect(marker1cluster10._iconNeedsUpdate).to.be.ok(); expect(marker1cluster2._iconNeedsUpdate).to.be.ok(); // Also check that visible clusters are "un-flagged" since they should be re-drawn. expect(marker1cluster5._iconNeedsUpdate).to.not.be.ok(); }); it('re-draws visible clusters', function () { group = L.markerClusterGroup({ iconCreateFunction: function (cluster) { var markers = cluster.getAllChildMarkers(); for(var i in markers) { if (markers[i].changed) { return new L.DivIcon({ className: "changed" }); } } return new L.DivIcon({ className: "original" }); } }).addTo(map); var marker1 = L.marker([1.5, 1.5]).addTo(group), marker2 = L.marker([1.5, 1.5]).addTo(group); // Needed to force a cluster. setMapView(); var marker1cluster9 = getClusterAtZoom(marker1, 9); // First go to some zoom levels so that Leaflet initializes clusters icons. expect(marker1cluster9._iconNeedsUpdate).to.be.ok(); map.setZoom(9, {animate: false}); expect(marker1cluster9._iconNeedsUpdate).to.not.be.ok(); expect(marker1cluster9._icon.className).to.contain("original"); expect(marker1cluster9._icon.className).to.not.contain("changed"); // Run any animation. clock.tick(1000); // Alter the marker. marker1.changed = true; // Then request clusters refresh. group.refreshClusters(marker1); // Now check that visible clusters icon is re-drawn. expect(marker1cluster9._icon.className).to.contain("changed"); expect(marker1cluster9._icon.className).to.not.contain("original"); }); // Shared code for the 2 below tests function iconCreateFunction(cluster) { var markers = cluster.getAllChildMarkers(); for(var i in markers) { if (markers[i].changed) { return new L.DivIcon({ className: "changed" }); } } return new L.DivIcon({ className: "original" }); } it('re-draws markers in singleMarkerMode', function () { group = L.markerClusterGroup({ singleMarkerMode: true, iconCreateFunction: iconCreateFunction }).addTo(map); var marker1 = L.marker([1.5, 1.5]).addTo(group); setMapView(); expect(marker1._icon.className).to.contain("original"); // Alter the marker. marker1.changed = true; // Then request clusters refresh. group.refreshClusters(marker1); expect(marker1._icon.className).to.contain("changed"); expect(marker1._icon.className).to.not.contain("original"); }); it('does not modify markers that do not belong to the current group (in singleMarkerMode)', function () { group = L.markerClusterGroup({ singleMarkerMode: true, iconCreateFunction: iconCreateFunction }).addTo(map); var marker1 = L.marker([1.5, 1.5]).addTo(group), marker2 = L.marker([1.5, 1.5], { icon: iconCreateFunction({ getAllChildMarkers: function () { return marker2; } }) }).addTo(map); setMapView(); expect(marker1._icon.className).to.contain("original"); expect(marker2._icon.className).to.contain("original"); // Alter the markers. marker1.changed = true; marker2.changed = true; // Then request clusters refresh. group.refreshClusters([marker1, marker2]); expect(marker1._icon.className).to.contain("changed"); expect(marker1._icon.className).to.not.contain("original"); expect(marker2._icon.className).to.contain("original"); expect(marker2._icon.className).to.not.contain("changed"); }); // Shared code for below tests. var marker1 = L.marker([1.5, 1.5]), marker2 = L.marker([1.5, 1.5]), // Needed to force a cluster. marker3 = L.marker([1.1, 1.1]), marker4 = L.marker([1.1, 1.1]), // Needed to force a cluster. marker5 = L.marker([1.9, 1.9]), marker6 = L.marker([1.9, 1.9]), // Needed to force a cluster. marker1cluster8, marker1cluster3, marker1cluster5, marker3cluster8, marker3cluster3, marker3cluster5, marker5cluster8, marker5cluster3, marker5cluster5; function init3clusterBranches() { group = L.markerClusterGroup({ maxClusterRadius: 2 // Make sure we keep distinct clusters. }).addTo(map); // Populate Marker Cluster Group. marker1.addTo(group); marker2.addTo(group); marker3.addTo(group); marker4.addTo(group); marker5.addTo(group); marker6.addTo(group); setMapView(); marker1cluster8 = getClusterAtZoom(marker1, 8); marker1cluster3 = getClusterAtZoom(marker1, 3); marker1cluster5 = getClusterAtZoom(marker1, 5); marker3cluster8 = getClusterAtZoom(marker3, 8); marker3cluster3 = getClusterAtZoom(marker3, 3); marker3cluster5 = getClusterAtZoom(marker3, 5); marker5cluster8 = getClusterAtZoom(marker5, 8); marker5cluster3 = getClusterAtZoom(marker5, 3); marker5cluster5 = getClusterAtZoom(marker5, 5); // Make sure we have 3 distinct clusters up to zoom level Z (let's choose Z = 3) expect(marker1cluster3._childCount).to.equal(2); expect(marker3cluster3._childCount).to.equal(2); expect(marker5cluster3._childCount).to.equal(2); // First go to some zoom levels so that Leaflet initializes clusters icons. expect(marker1cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker5cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker1cluster3._iconNeedsUpdate).to.be.ok(); expect(marker3cluster3._iconNeedsUpdate).to.be.ok(); expect(marker5cluster3._iconNeedsUpdate).to.be.ok(); map.setZoom(3, {animate: false}); expect(marker1cluster3._iconNeedsUpdate).to.not.be.ok(); expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok(); expect(marker5cluster3._iconNeedsUpdate).to.not.be.ok(); // Finish on an intermediate zoom level. expect(marker1cluster5._iconNeedsUpdate).to.be.ok(); expect(marker3cluster5._iconNeedsUpdate).to.be.ok(); expect(marker5cluster5._iconNeedsUpdate).to.be.ok(); map.setZoom(5, {animate: false}); expect(marker1cluster5._iconNeedsUpdate).to.not.be.ok(); expect(marker3cluster5._iconNeedsUpdate).to.not.be.ok(); expect(marker5cluster5._iconNeedsUpdate).to.not.be.ok(); // Run any animation. clock.tick(1000); // Ready to refresh clusters with method of choice and assess result. } it('does not flag clusters of other markers', function () { init3clusterBranches(); // Then request clusters refresh. // No need to actually modify the marker. group.refreshClusters(marker1); // Now check that non-visible clusters are flagged as "dirty". expect(marker1cluster8._iconNeedsUpdate).to.be.ok(); expect(marker1cluster3._iconNeedsUpdate).to.be.ok(); // Finally check that non-involved clusters are not "dirty". expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok(); expect(marker5cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker5cluster3._iconNeedsUpdate).to.not.be.ok(); }); it('processes itself when no argument is passed', function () { init3clusterBranches(); // Then request clusters refresh. // No need to actually modify the marker. group.refreshClusters(); // Now check that non-visible clusters are flagged as "dirty". expect(marker1cluster8._iconNeedsUpdate).to.be.ok(); expect(marker1cluster3._iconNeedsUpdate).to.be.ok(); expect(marker3cluster8._iconNeedsUpdate).to.be.ok(); expect(marker3cluster3._iconNeedsUpdate).to.be.ok(); expect(marker5cluster8._iconNeedsUpdate).to.be.ok(); expect(marker5cluster3._iconNeedsUpdate).to.be.ok(); }); it('accepts an array of markers', function () { init3clusterBranches(); // Then request clusters refresh. // No need to actually modify the markers. group.refreshClusters([marker1, marker5]); // Clusters of marker3 and 4 shall not be flagged. // Now check that non-visible clusters are flagged as "dirty". expect(marker1cluster8._iconNeedsUpdate).to.be.ok(); expect(marker1cluster3._iconNeedsUpdate).to.be.ok(); expect(marker5cluster8._iconNeedsUpdate).to.be.ok(); expect(marker5cluster3._iconNeedsUpdate).to.be.ok(); // Clusters of marker3 and 4 shall not be flagged. expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok(); }); it('accepts a mapping of markers', function () { init3clusterBranches(); // Then request clusters refresh. // No need to actually modify the markers. group.refreshClusters({ id1: marker1, id2: marker5 }); // Clusters of marker3 and 4 shall not be flagged. // Now check that non-visible clusters are flagged as "dirty". expect(marker1cluster8._iconNeedsUpdate).to.be.ok(); expect(marker1cluster3._iconNeedsUpdate).to.be.ok(); expect(marker5cluster8._iconNeedsUpdate).to.be.ok(); expect(marker5cluster3._iconNeedsUpdate).to.be.ok(); // Clusters of marker3 and 4 shall not be flagged. expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok(); }); it('accepts an L.LayerGroup', function () { init3clusterBranches(); // Then request clusters refresh. // No need to actually modify the markers. var layerGroup = new L.LayerGroup([marker1, marker5]); group.refreshClusters(layerGroup); // Clusters of marker3 and 4 shall not be flagged. // Now check that non-visible clusters are flagged as "dirty". expect(marker1cluster8._iconNeedsUpdate).to.be.ok(); expect(marker1cluster3._iconNeedsUpdate).to.be.ok(); expect(marker5cluster8._iconNeedsUpdate).to.be.ok(); expect(marker5cluster3._iconNeedsUpdate).to.be.ok(); // Clusters of marker3 and 4 shall not be flagged. expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok(); }); it('accepts an L.MarkerCluster', function () { init3clusterBranches(); // Then request clusters refresh. // No need to actually modify the markers. group.refreshClusters(marker1cluster8); // Clusters of marker3, 4, 5 and 6 shall not be flagged. // Now check that non-visible clusters are flagged as "dirty". expect(marker1cluster8._iconNeedsUpdate).to.be.ok(); expect(marker1cluster3._iconNeedsUpdate).to.be.ok(); // Clusters of marker3 and 4 shall not be flagged. expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok(); expect(marker5cluster8._iconNeedsUpdate).to.not.be.ok(); expect(marker5cluster3._iconNeedsUpdate).to.not.be.ok(); }); });