Skip to content
14 changes: 7 additions & 7 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ module.exports = [
...config,
rules: {
...config.rules,
"prettier/prettier": [
"error",
{
singleQuote: false,
trailingComma: "es5",
},
],

quotes: ["warn", "double"],
eqeqeq: ["error", "always"],
},
})),
{
files: ["**/*.test.ts"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
},
},
];
23 changes: 8 additions & 15 deletions src/algorithms/core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,14 @@
* limitations under the License.
*/

import { initialize } from "@googlemaps/jest-mocks";
import { initializeMocks, testMarkerTypes } from "../test-helpers";
import { noop } from "./core";

initialize();
const markerClasses = [
google.maps.Marker,
google.maps.marker.AdvancedMarkerElement,
];
initializeMocks();

describe.each(markerClasses)(
"Core works with legacy and Advanced Markers",
(markerClass) => {
test("noop should return equivalent number of clusters", () => {
expect(noop([]).length).toBe(0);
expect(noop([new markerClass({}), new markerClass({})]).length).toBe(2);
});
}
);
describe.each(testMarkerTypes)("Core works with %s", (_, markerClass) => {
test("noop should return equivalent number of clusters", () => {
expect(noop([]).length).toBe(0);
expect(noop([new markerClass({}), new markerClass({})]).length).toBe(2);
});
});
21 changes: 9 additions & 12 deletions src/algorithms/grid.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@
*/

import { GridAlgorithm } from "./grid";
import { initialize, MapCanvasProjection } from "@googlemaps/jest-mocks";
import { initializeMocks, testMarkerTypes } from "../test-helpers";
import { MapCanvasProjection } from "@googlemaps/jest-mocks";

initialize();
const markers = [
new google.maps.Marker(),
new google.maps.marker.AdvancedMarkerElement(),
];
initializeMocks();

describe.each(markers)(
"Grid works with legacy and Advanced Markers",
(marker) => {
describe.each(testMarkerTypes)(
"GridAlgorithm works with %s",
(_, markerClass) => {
let map: google.maps.Map;

beforeEach(() => {
Expand All @@ -34,7 +31,7 @@ describe.each(markers)(

test("calculate should return changed: true for first call when zoom > max zoom", () => {
const mapCanvasProjection = new MapCanvasProjection();
const markers = [marker];
const markers = [new markerClass()];

const grid = new GridAlgorithm({ maxZoom: 16 });
grid["noop"] = jest.fn();
Expand Down Expand Up @@ -62,7 +59,7 @@ describe.each(markers)(
test("calculate should return changed: false when zoom doesn't change", () => {
const mapCanvasProjection =
jest.fn() as unknown as google.maps.MapCanvasProjection;
const markers = [marker];
const markers = [new markerClass()];

const grid = new GridAlgorithm({ maxZoom: 16 });
grid["noop"] = jest.fn();
Expand All @@ -89,7 +86,7 @@ describe.each(markers)(
test("calculate should return changed: false for next calls at or above max zoom, even if zoom changed", () => {
const mapCanvasProjection =
jest.fn() as unknown as google.maps.MapCanvasProjection;
const markers = [marker];
const markers = [new markerClass()];

const grid = new GridAlgorithm({ maxZoom: 16 });
grid["noop"] = jest.fn();
Expand Down
27 changes: 10 additions & 17 deletions src/algorithms/supercluster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@
*/

import { SuperClusterAlgorithm } from "./supercluster";
import { initialize } from "@googlemaps/jest-mocks";
import {
initializeMocks,
testMarkerTypes,
setupMapBounds,
} from "../test-helpers";
import { Marker } from "../marker-utils";
import { ClusterFeature } from "supercluster";

initialize();
const markerClasses = [
google.maps.Marker,
google.maps.marker.AdvancedMarkerElement,
];
initializeMocks();

describe.each(markerClasses)(
"SuperCluster works with legacy and Advanced Markers",
(markerClass) => {
describe.each(testMarkerTypes)(
"SuperClusterAlgorithm works with %s",
(_, markerClass) => {
let map: google.maps.Map;

beforeEach(() => {
Expand Down Expand Up @@ -62,14 +62,7 @@ describe.each(markerClasses)(

const superCluster = new SuperClusterAlgorithm({});
map.getZoom = jest.fn().mockReturnValue(0);
map.getBounds = jest.fn().mockReturnValue({
toJSON: () => ({
west: -180,
south: -90,
east: 180,
north: 90,
}),
});
setupMapBounds(map, { west: -180, south: -90, east: 180, north: 90 });
const { clusters } = superCluster.calculate({
markers,
map,
Expand Down
32 changes: 19 additions & 13 deletions src/algorithms/supercluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { AbstractAlgorithm, AlgorithmInput, AlgorithmOutput } from "./core";
import SuperCluster, { ClusterFeature } from "supercluster";
import { deepEqual } from "fast-equals";
import { AbstractAlgorithm, AlgorithmInput, AlgorithmOutput } from "./core";
import { MarkerUtils, Marker } from "../marker-utils";
import { Cluster } from "../cluster";
import { deepEqual } from "fast-equals";
import { assertNotNull } from "../utils";
import { areClustersEqual, areMarkersEqual } from "./utils";

export type SuperClusterOptions = SuperCluster.Options<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -50,7 +50,7 @@ export class SuperClusterAlgorithm extends AbstractAlgorithm {
}

public calculate(input: AlgorithmInput): AlgorithmOutput {
let changed = false;
let inputsChanged = false;
let zoom = input.map.getZoom();

assertNotNull(zoom);
Expand All @@ -59,14 +59,15 @@ export class SuperClusterAlgorithm extends AbstractAlgorithm {

const state = { zoom: zoom };

if (!deepEqual(input.markers, this.markers)) {
changed = true;
// TODO use proxy to avoid copy?
if (!areMarkersEqual(input.markers, this.markers)) {
inputsChanged = true;

this.markers = [...input.markers];

const points = this.markers.map((marker) => {
const position = MarkerUtils.getPosition(marker);
const coordinates = [position.lng(), position.lat()];

return {
type: "Feature",
geometry: { type: "Point", coordinates },
Expand All @@ -76,9 +77,9 @@ export class SuperClusterAlgorithm extends AbstractAlgorithm {
this.superCluster.load(points);
}

if (!changed) {
if (!inputsChanged) {
if (this.state.zoom <= this.maxZoom || state.zoom <= this.maxZoom) {
changed = !deepEqual(this.state, state);
inputsChanged = !deepEqual(this.state, state);
}
}

Expand All @@ -88,14 +89,19 @@ export class SuperClusterAlgorithm extends AbstractAlgorithm {
if (input.markers.length === 0) {
this.clusters = [];

return { clusters: this.clusters, changed };
return { clusters: this.clusters, changed: inputsChanged };
}

if (changed) {
this.clusters = this.cluster(input);
let clustersChanged = false;
if (inputsChanged) {
const newClusters = this.cluster(input);

clustersChanged = !areClustersEqual(this.clusters, newClusters);

this.clusters = newClusters;
}

return { clusters: this.clusters, changed };
return { clusters: this.clusters, changed: clustersChanged };
}

public cluster({ map }: AlgorithmInput): Cluster[] {
Expand Down
Loading
Loading