UNPKG

leaflet.glify

Version:
489 lines (482 loc) 15 kB
import { Glify } from "./index"; import { IPointsSettings, Points } from "./points"; import { ILinesSettings, Lines } from "./lines"; import { IShapesSettings, Shapes } from "./shapes"; import { LatLng, LeafletMouseEvent, Map, Point } from "leaflet"; import { FeatureCollection, LineString, MultiPolygon } from "geojson"; jest.mock("./canvas-overlay"); type mouseEventFunction = (e: LeafletMouseEvent) => void; jest.mock("./utils", () => { return { debounce: (fn: mouseEventFunction) => { return (e: LeafletMouseEvent) => fn(e); }, }; }); describe("glify", () => { describe("longitudeFirst", () => { it("sets longitudeKey as 0 and latitudeKey as 1", () => { const glify = new Glify().longitudeFirst(); expect(glify.longitudeKey).toBe(0); expect(glify.latitudeKey).toBe(1); }); }); describe("latitudeFirst", () => { it("sets longitudeKey as 1 and latitudeKey as 0", () => { const glify = new Glify().latitudeFirst(); expect(glify.longitudeKey).toBe(1); expect(glify.latitudeKey).toBe(0); }); }); describe("instances", () => { it("groups all instances together", () => { const glify = new Glify(); const data: number[][] = [[1, 2]]; const size = 1; const map = new Map(document.createElement("div")); const points = glify.points({ data, size, map, }); const lines = glify.lines({ data: { type: "FeatureCollection", features: [], }, weight: size, map, }); const shapes = glify.shapes({ data: { type: "FeatureCollection", features: [], }, map, }); expect(glify.instances).toEqual([points, lines, shapes]); expect(new Glify().instances).toEqual([]); }); }); describe("points", () => { let glify: Glify; let constructorSpy: jest.Mock; beforeEach(() => { glify = new Glify(); constructorSpy = jest.fn((settings: Partial<IPointsSettings>) => {}); glify.Points = class SpyPoints extends Points { constructor(settings: Partial<IPointsSettings>) { super(settings); constructorSpy(settings); } }; }); it("calls new this.Points with proper properties and pushes to pointsInstances", () => { const data: number[][] = [[1, 2]]; const size = 1; const map = new Map(document.createElement("div")); expect(glify.pointsInstances.length).toBe(0); const points = glify.points({ data, size, map, latitudeKey: 1, longitudeKey: 1, }); expect(glify.pointsInstances.length).toBe(1); expect(constructorSpy).toHaveBeenCalledWith({ map, size, data, setupClick: points.settings.setupClick, setupHover: points.settings.setupHover, latitudeKey: 1, longitudeKey: 1, vertexShaderSource: points.settings.vertexShaderSource, fragmentShaderSource: points.settings.fragmentShaderSource, }); }); }); describe("lines", () => { let glify: Glify; let constructorSpy: jest.Mock; beforeEach(() => { glify = new Glify(); constructorSpy = jest.fn((settings: Partial<ILinesSettings>) => {}); glify.Lines = class SpyPoints extends Lines { constructor(settings: Partial<ILinesSettings>) { super(settings); constructorSpy(settings); } }; }); it("calls new this.Lines with proper properties and pushes to linesInstances", () => { const data: FeatureCollection<LineString> = { type: "FeatureCollection", features: [], }; const weight = 1; const map = new Map(document.createElement("div")); expect(glify.linesInstances.length).toBe(0); const lines = glify.lines({ data, weight, map, latitudeKey: 1, longitudeKey: 1, }); expect(glify.linesInstances.length).toBe(1); expect(constructorSpy).toHaveBeenCalledWith({ map, weight, data, setupClick: lines.settings.setupClick, setupHover: lines.settings.setupHover, latitudeKey: 1, longitudeKey: 1, vertexShaderSource: lines.settings.vertexShaderSource, fragmentShaderSource: lines.settings.fragmentShaderSource, }); }); }); describe("shapes", () => { let glify: Glify; let constructorSpy: jest.Mock; beforeEach(() => { glify = new Glify(); constructorSpy = jest.fn((settings: Partial<IShapesSettings>) => {}); glify.Shapes = class SpyPoints extends Shapes { constructor(settings: Partial<IShapesSettings>) { super(settings); constructorSpy(settings); } }; }); it("calls new this.Shapes with proper properties and pushes to shapesInstances", () => { const data: FeatureCollection<MultiPolygon> = { type: "FeatureCollection", features: [], }; const map = new Map(document.createElement("div")); expect(glify.shapesInstances.length).toBe(0); const shapes = glify.shapes({ data, map, latitudeKey: 2, longitudeKey: 3, }); expect(glify.shapesInstances.length).toBe(1); expect(constructorSpy).toHaveBeenCalledWith({ map, data, setupClick: shapes.settings.setupClick, setupHover: shapes.settings.setupHover, latitudeKey: 2, longitudeKey: 3, vertexShaderSource: shapes.settings.vertexShaderSource, fragmentShaderSource: shapes.settings.fragmentShaderSource, }); }); }); describe("setupClick", () => { describe("when this.clickSetupMaps does not include map", () => { it("pushes it to glify.maps", () => { const glify = new Glify(); const element = document.createElement("div"); const map = new Map(element); expect(glify.clickSetupMaps.length).toBe(0); glify.setupClick(map); expect(glify.clickSetupMaps.length).toBe(1); }); }); describe("when this.clickSetupMaps includes map", () => { it("returns early", () => { const glify = new Glify(); const element = document.createElement("div"); const map = new Map(element); glify.clickSetupMaps.push(map); expect(glify.clickSetupMaps.length).toBe(1); glify.setupClick(map); expect(glify.clickSetupMaps.length).toBe(1); }); }); it('calls map.on("click") correctly', () => { const glify = new Glify(); const element = document.createElement("div"); const map = new Map(element); jest.spyOn(map, "on"); glify.setupClick(map); expect(map.on).toHaveBeenCalled(); }); describe("when a click occurs", () => { let glify: Glify; let map: Map; let element: HTMLElement; let pointsTryClickSpy: jest.SpyInstance; let linesTryClickSpy: jest.SpyInstance; let shapesTryClickSpy: jest.SpyInstance; let latlng: LatLng; let layerPoint: Point; let containerPoint: Point; beforeEach(() => { glify = new Glify(); glify.Points = PointsSpy; glify.Lines = LinesSpy; glify.Shapes = ShapesSpy; pointsTryClickSpy = jest.spyOn(glify.Points, "tryClick"); linesTryClickSpy = jest.spyOn(glify.Lines, "tryClick"); shapesTryClickSpy = jest.spyOn(glify.Shapes, "tryClick"); element = document.createElement("div"); map = new Map(element); glify.setupClick(map); map.setView([10, 10], 7); latlng = new LatLng(1, 1); layerPoint = map.latLngToLayerPoint(latlng); containerPoint = map.latLngToContainerPoint(latlng); }); afterEach(() => { pointsTryClickSpy.mockRestore(); linesTryClickSpy.mockRestore(); shapesTryClickSpy.mockRestore(); }); describe("calling Points.tryClick", () => { describe("when Points.tryClick returns undefined", () => { it("continues on to Lines", () => { map.fireEvent("click", { latlng, layerPoint, containerPoint, }); expect(pointsTryClickSpy.mock.calls[0][0]).toEqual({ containerPoint, latlng, layerPoint, sourceTarget: map, target: map, type: "click", }); expect(linesTryClickSpy.mock.calls[0][0]).toEqual({ containerPoint, latlng, layerPoint, sourceTarget: map, target: map, type: "click", }); }); }); describe("when Points.tryClick returns a value", () => { beforeEach(() => { PointsSpy.tryCLickResult = false; }); afterEach(() => { delete PointsSpy.tryCLickResult; }); it("returns early", () => { map.fireEvent("click", { latlng, layerPoint, containerPoint, }); expect(pointsTryClickSpy.mock.calls[0][0]).toEqual({ containerPoint, latlng, layerPoint, sourceTarget: map, target: map, type: "click", }); expect(linesTryClickSpy).not.toHaveBeenCalled(); }); }); }); describe("calling Lines.tryClick", () => { describe("when Lines.tryClick returns undefined", () => { it("continues on to Shapes", () => { map.fireEvent("click", { latlng, layerPoint, containerPoint, }); expect(linesTryClickSpy.mock.calls[0][0]).toEqual({ containerPoint, latlng, layerPoint, sourceTarget: map, target: map, type: "click", }); expect(shapesTryClickSpy.mock.calls[0][0]).toEqual({ containerPoint, latlng, layerPoint, sourceTarget: map, target: map, type: "click", }); }); }); describe("when Lines.tryClick returns a value", () => { beforeEach(() => { LinesSpy.tryCLickResult = false; }); afterEach(() => { delete LinesSpy.tryCLickResult; }); it("returns early", () => { map.fireEvent("click", { latlng, layerPoint, containerPoint, }); expect(linesTryClickSpy.mock.calls[0][0]).toEqual({ containerPoint, latlng, layerPoint, sourceTarget: map, target: map, type: "click", }); expect(shapesTryClickSpy).not.toHaveBeenCalled(); }); }); }); }); }); describe("setupHover", () => { describe("when this.clickSetupMaps does not include map", () => { it("pushes it to glify.maps", () => { const glify = new Glify(); const element = document.createElement("div"); const map = new Map(element); expect(glify.hoverSetupMaps.length).toBe(0); glify.setupHover(map); expect(glify.hoverSetupMaps.length).toBe(1); }); }); describe("when this.clickSetupMaps includes map", () => { it("returns early", () => { const glify = new Glify(); const element = document.createElement("div"); const map = new Map(element); glify.hoverSetupMaps.push(map); expect(glify.hoverSetupMaps.length).toBe(1); glify.setupHover(map); expect(glify.hoverSetupMaps.length).toBe(1); }); }); describe("when a hover occurs", () => { let glify: Glify; let map: Map; let element: HTMLElement; let latlng: LatLng; let layerPoint: Point; let containerPoint: Point; let pointsTryHoverSpy: jest.SpyInstance; let linesTryHoverSpy: jest.SpyInstance; let shapesTryHoverSpy: jest.SpyInstance; beforeEach(() => { glify = new Glify(); glify.Points = PointsSpy; glify.Lines = LinesSpy; glify.Shapes = ShapesSpy; pointsTryHoverSpy = jest.spyOn(glify.Points, "tryHover"); linesTryHoverSpy = jest.spyOn(glify.Lines, "tryHover"); shapesTryHoverSpy = jest.spyOn(glify.Shapes, "tryHover"); element = document.createElement("div"); map = new Map(element); glify.setupHover(map); map.setView([10, 10], 7); latlng = new LatLng(1, 1); layerPoint = map.latLngToLayerPoint(latlng); containerPoint = map.latLngToContainerPoint(latlng); }); afterEach(() => { pointsTryHoverSpy.mockRestore(); linesTryHoverSpy.mockRestore(); shapesTryHoverSpy.mockRestore(); }); it("calls tryHover on Points, Lines, and Shapes", () => { map.fireEvent("mousemove", { latlng, layerPoint, containerPoint, }); const expected = { containerPoint, latlng, layerPoint, sourceTarget: map, target: map, type: "mousemove", }; expect(pointsTryHoverSpy).toHaveBeenCalledWith( expected, map, glify.pointsInstances ); expect(linesTryHoverSpy).toHaveBeenCalledWith( expected, map, glify.linesInstances ); expect(shapesTryHoverSpy).toHaveBeenCalledWith( expected, map, glify.shapesInstances ); }); }); }); }); class PointsSpy extends Points { static tryCLickResult: boolean | undefined; static tryClick( e: LeafletMouseEvent, map: Map, instances: Points[] ): boolean | undefined { return this.tryCLickResult; } static tryHover( e: LeafletMouseEvent, map: Map, instances: Points[] ): boolean[] { return []; } } class LinesSpy extends Lines { static tryCLickResult: boolean | undefined; static tryClick( e: LeafletMouseEvent, map: Map, instances: Lines[] ): boolean | undefined { return this.tryCLickResult; } static tryHover( e: LeafletMouseEvent, map: Map, instances: Lines[] ): boolean[] { return []; } } class ShapesSpy extends Shapes { static tryCLickResult: boolean | undefined; static tryClick( e: LeafletMouseEvent, map: Map, instances: Shapes[] ): boolean | undefined { return this.tryCLickResult; } static tryHover( e: LeafletMouseEvent, map: Map, instances: Shapes[] ): boolean[] { return []; } }