leaflet.glify
Version:
web gl renderer plugin for leaflet
978 lines (945 loc) • 33 kB
text/typescript
import {
BaseGlLayer,
defaultHoverWait,
defaultPane,
EventCallback,
IBaseGlLayerSettings,
} from "./base-gl-layer";
import { ICanvasOverlayDrawEvent } from "./canvas-overlay";
import { LatLng, LatLngBounds, LeafletMouseEvent, Map, Point } from "leaflet";
jest.mock("./canvas-overlay");
describe("BaseGlLayer", () => {
interface ITestLayerSettings extends IBaseGlLayerSettings {}
class TestLayer extends BaseGlLayer<ITestLayerSettings> {
drawOnCanvas(context: ICanvasOverlayDrawEvent): this {
return this;
}
render(): this {
return this;
}
}
const defaultSettings: Partial<ITestLayerSettings> = {
longitudeKey: 1,
latitudeKey: 0,
data: {},
pane: "",
};
function getGlLayer(settings?: Partial<ITestLayerSettings>) {
const element = document.createElement("div");
const map = new Map(element);
const vertexShaderSource = ` `;
const fragmentShaderSource = ` `;
return new TestLayer({
...defaultSettings,
map,
vertexShaderSource,
fragmentShaderSource,
...settings,
});
}
function fakeEvent(layer: TestLayer): LeafletMouseEvent {
return {
type: "fake event",
latlng: new LatLng(1, 1),
layerPoint: new Point(1, 1),
containerPoint: new Point(1, 1),
originalEvent: new MouseEvent("fake event"),
target: "",
sourceTarget: "",
propagatedFrom: "",
layer,
};
}
describe("data", () => {
describe("when settings.data is falsey", () => {
it("throws", () => {
const data = null;
const layer = getGlLayer({ data });
expect(() => {
layer.data;
}).toThrow();
});
});
describe("when settings.data is defined", () => {
it("is returned", () => {
const data = { features: [] };
const layer = getGlLayer({ data });
expect(layer.data).toBe(data);
});
});
});
describe("pane", () => {
describe("when not defined in settings.pane", () => {
it("returns defaultPane value", () => {
const layer = getGlLayer({ pane: undefined });
expect(layer.settings.pane).toBe(undefined);
expect(layer.pane).toBe(defaultPane);
});
});
describe("when defined in settings.pane", () => {
it("returns settings.pane", () => {
const layer = getGlLayer({ pane: "pane" });
expect(layer.settings.pane).toBe("pane");
expect(layer.pane).toBe("pane");
});
});
});
describe("className", () => {
describe("when not defined in settings.className", () => {
it("returns empty string", () => {
const layer = getGlLayer({ className: undefined });
expect(layer.className).toBe("");
});
});
describe("when defined in settings.className", () => {
it("is returned", () => {
const layer = getGlLayer({ className: "className" });
expect(layer.className).toBe("className");
});
});
});
describe("map", () => {
describe("when settings.map is not defined", () => {
it("throws", () => {
const layer = getGlLayer();
delete layer.settings.map;
expect(() => {
layer.map;
}).toThrow();
});
});
describe("when settings.map is defined", () => {
it("is returned", () => {
const layer = getGlLayer();
expect(layer.settings.map).not.toBeFalsy();
expect(layer.map).toBe(layer.settings.map);
});
});
});
describe("sensitivity", () => {
describe("when settings.sensitivity is not defined", () => {
it("throws", () => {
const layer = getGlLayer();
delete layer.settings.sensitivity;
expect(() => {
layer.sensitivity;
}).toThrow();
});
});
describe("when settings.sensitivity is defined", () => {
it("is returned", () => {
const layer = getGlLayer({ sensitivity: 1 });
expect(layer.settings.sensitivity).toBe(1);
expect(layer.sensitivity).toBe(layer.settings.sensitivity);
});
});
});
describe("sensitivityHover", () => {
describe("when settings.sensitivityHover is not defined", () => {
it("throws", () => {
const layer = getGlLayer();
delete layer.settings.sensitivityHover;
expect(() => {
layer.sensitivityHover;
}).toThrow();
});
});
describe("when settings.sensitivityHover is defined", () => {
it("is returned", () => {
const layer = getGlLayer({ sensitivityHover: 1 });
expect(layer.settings.sensitivityHover).toBe(1);
expect(layer.sensitivityHover).toBe(layer.settings.sensitivityHover);
});
});
});
describe("hoverWait", () => {
describe("when not defined in settings.hoverWait", () => {
it("returns empty string", () => {
const layer = getGlLayer({ hoverWait: undefined });
expect(layer.hoverWait).toBe(defaultHoverWait);
});
});
describe("when defined in settings.hoverWait", () => {
it("is returned", () => {
const layer = getGlLayer({ hoverWait: 123 });
expect(layer.hoverWait).toBe(123);
});
});
});
describe("longitudeKey", () => {
describe("when settings.longitudeKey is not defined", () => {
it("throws", () => {
const layer = getGlLayer();
delete layer.settings.longitudeKey;
expect(() => {
layer.longitudeKey;
}).toThrow();
});
});
describe("when settings.longitudeKey is defined", () => {
it("is returned", () => {
const layer = getGlLayer({ longitudeKey: 1 });
expect(layer.settings.longitudeKey).toBe(1);
expect(layer.longitudeKey).toBe(layer.settings.longitudeKey);
});
});
});
describe("latitudeKey", () => {
describe("when settings.latitudeKey is not defined", () => {
it("throws", () => {
const layer = getGlLayer();
delete layer.settings.latitudeKey;
expect(() => {
layer.latitudeKey;
}).toThrow();
});
});
describe("when settings.longitudeKey is defined", () => {
it("is returned", () => {
const layer = getGlLayer({ latitudeKey: 1 });
expect(layer.settings.latitudeKey).toBe(1);
expect(layer.latitudeKey).toBe(layer.settings.latitudeKey);
});
});
});
describe("opacity", () => {
describe("when settings.opacity is not defined", () => {
it("throws", () => {
const layer = getGlLayer();
delete layer.settings.opacity;
expect(() => {
layer.opacity;
}).toThrow();
});
});
describe("when settings.opacity is defined", () => {
it("is returned", () => {
const layer = getGlLayer({ opacity: 1 });
expect(layer.settings.opacity).toBe(1);
expect(layer.opacity).toBe(layer.settings.opacity);
});
});
});
describe("color", () => {
describe("when settings.color is not defined", () => {
it("returns null", () => {
const layer = getGlLayer();
delete layer.settings.color;
expect(layer.color).toBeNull();
});
});
describe("when settings.color is defined", () => {
it("is returned", () => {
const color = { r: 1, g: 1, b: 1, a: 1 };
const layer = getGlLayer({ color });
expect(layer.settings.color).toBe(color);
expect(layer.color).toBe(layer.settings.color);
});
});
});
describe("constructor", () => {
it("sets settings from first argument", () => {
const element = document.createElement("div");
const map = new Map(element);
const layer = new TestLayer({ ...defaultSettings, map });
expect(layer.settings.map).toBe(map);
});
it("calls this.canvas.getContext, with preserveDrawingBuffer as boolean and sets this.gl", () => {
const element = document.createElement("div");
const map = new Map(element);
const layer = new TestLayer({
...defaultSettings,
map,
preserveDrawingBuffer: true,
});
expect(layer.canvas.getContext).toHaveBeenCalledWith("webgl2", {
preserveDrawingBuffer: true,
});
expect(layer.gl).toBeInstanceOf(WebGLRenderingContext);
});
it("provides a drawOnCanvas lambda, that calls layer.drawOnCanvas", () => {
const layer = getGlLayer();
jest.spyOn(layer, "drawOnCanvas");
const event: ICanvasOverlayDrawEvent = {
canvas: document.createElement("canvas"),
bounds: new LatLngBounds(new LatLng(1, 1), new LatLng(10, 10)),
offset: new Point(1, 1),
scale: 1,
size: new Point(10, 10),
zoomScale: 1,
zoom: 1,
};
layer.layer._userDrawFunc(event);
expect(layer.drawOnCanvas).toHaveBeenCalledWith(event);
});
});
describe("attachShaderVariables", () => {
describe("shaderVariableCount is 0", () => {
it("return early", () => {
const element = document.createElement("div");
const map = new Map(element);
const layer = new TestLayer({ ...defaultSettings, map });
jest.spyOn(layer, "getAttributeLocation");
expect(layer.attachShaderVariables(4)).toBe(layer);
expect(layer.getAttributeLocation).not.toHaveBeenCalled();
});
});
describe("shaderVariableCount is 2", () => {
it("attaches and enables variables", () => {
const element = document.createElement("div");
const map = new Map(element);
const layer = new TestLayer({
...defaultSettings,
map,
shaderVariables: {
one: {
type: "FLOAT",
start: 0,
size: 2,
},
two: {
type: "FLOAT",
start: 3,
size: 4,
},
},
});
jest.spyOn(layer, "getAttributeLocation");
jest.spyOn(layer.gl, "getAttribLocation").mockReturnValue(999);
jest.spyOn(layer.gl, "vertexAttribPointer");
jest.spyOn(layer.gl, "enableVertexAttribArray");
layer.program = new WebGLProgram();
expect(layer.attachShaderVariables(4)).toBe(layer);
expect(layer.getAttributeLocation).toHaveBeenCalledWith("one");
expect(layer.getAttributeLocation).toHaveBeenCalledWith("two");
expect(layer.gl.vertexAttribPointer).toHaveBeenCalledWith(
999,
2,
layer.gl.FLOAT,
false,
0,
0
);
expect(layer.gl.vertexAttribPointer).toHaveBeenCalledWith(
999,
4,
layer.gl.FLOAT,
false,
0,
8
);
expect(layer.gl.enableVertexAttribArray).toHaveBeenCalledWith(999);
expect(layer.gl.enableVertexAttribArray).toHaveBeenCalledWith(999);
});
});
describe("getShaderVariableCount", () => {
it("returns the count of shaderVariables", () => {
const element = document.createElement("div");
const map = new Map(element);
const layer0 = new TestLayer({ ...defaultSettings, map });
expect(layer0.getShaderVariableCount()).toBe(0);
const layer1 = new TestLayer({
...defaultSettings,
map,
shaderVariables: {
one: {
type: "FLOAT",
start: 0,
size: 2,
},
},
});
expect(layer1.getShaderVariableCount()).toBe(1);
});
});
});
describe("setData", () => {
it("sets up settings with new data", () => {
const element = document.createElement("div");
const map = new Map(element);
const layer = new TestLayer({ ...defaultSettings, map });
const { settings } = layer;
const data = {};
layer.setData(data);
expect(settings).not.toBe(layer.settings);
expect(layer.data).toBe(data);
});
it("calls this.render()", () => {
const layer = getGlLayer();
jest.spyOn(layer, "render");
layer.setData([]);
expect(layer.render).toHaveBeenCalled();
});
});
describe("setup", () => {
describe("when settings.click and settings.setupClick are truth", () => {
it("calls settings.setupClick with this.map", () => {
const click = () => {};
const setupClick = jest.fn();
const layer = getGlLayer({
click,
setupClick,
});
expect(layer.setup()).toBe(layer);
expect(setupClick).toHaveBeenCalledWith(layer.map);
});
});
describe("when settings.hover and settings.setupHover are truthy", () => {
it("calls settings.setupHover with this.map and settings.hoverWait", () => {
const hover: EventCallback = () => {};
const setupHover = jest.fn();
const hoverWait = 12;
const layer = getGlLayer({
hover,
setupHover,
hoverWait,
});
expect(layer.setup()).toBe(layer);
expect(setupHover).toHaveBeenCalledWith(layer.map, hoverWait);
});
});
it("calls this.setupVertexShader, this.setupFragmentShader, and this.setupProgram", () => {
const layer = getGlLayer();
jest.spyOn(layer, "setupVertexShader");
jest.spyOn(layer, "setupFragmentShader");
jest.spyOn(layer, "setupProgram");
layer.setup();
expect(layer.setupVertexShader).toHaveBeenCalled();
expect(layer.setupFragmentShader).toHaveBeenCalled();
expect(layer.setupProgram).toHaveBeenCalled();
});
});
describe("setupVertexShader", () => {
it("sets this.vertexShader", () => {
const layer = getGlLayer();
layer.setupVertexShader();
expect(layer.vertexShader).not.toBe(null);
});
describe("when typeof settings.vertexShaderSource is a function", () => {
it("calls it, and calls gl.shaderSource with returned value", () => {
const vertexShaderSource = () => "vertex";
const layer = getGlLayer({ vertexShaderSource });
jest.spyOn(layer.gl, "shaderSource");
layer.setupVertexShader();
expect(layer.gl.shaderSource).toHaveBeenCalledWith(
layer.vertexShader,
"vertex"
);
});
});
describe("when typeof settings.vertexShaderSource is a string", () => {
it("calls gl.shaderSource with it", () => {
const vertexShaderSource = "vertex";
const layer = getGlLayer({ vertexShaderSource });
jest.spyOn(layer.gl, "shaderSource");
layer.setupVertexShader();
expect(layer.gl.shaderSource).toHaveBeenCalledWith(
layer.vertexShader,
"vertex"
);
});
});
describe("when vertexShader returns null", () => {
it("throws", () => {
const layer = getGlLayer();
jest.spyOn(layer.gl, "createShader").mockReturnValue(null);
expect(() => {
layer.setupVertexShader();
}).toThrow();
});
});
describe("when vertexShaderSource is undefined", () => {
it("throws", () => {
const layer = getGlLayer({ vertexShaderSource: undefined });
expect(() => {
layer.setupVertexShader();
}).toThrow();
});
});
it("calls gl.compileShader with vertexShader", () => {
const layer = getGlLayer();
jest.spyOn(layer.gl, "compileShader");
layer.setupVertexShader();
expect(layer.gl.compileShader).toBeCalledWith(layer.vertexShader);
});
});
describe("setupFragmentShader", () => {
it("sets this.fragmentShader", () => {
const layer = getGlLayer();
layer.setupFragmentShader();
expect(layer.fragmentShader).not.toBe(null);
});
describe("when typeof settings.fragmentShaderSource is a function", () => {
it("calls it, and calls gl.shaderSource with returned value", () => {
const fragmentShaderSource = () => "fragment";
const layer = getGlLayer({ fragmentShaderSource });
jest.spyOn(layer.gl, "shaderSource");
layer.setupFragmentShader();
expect(layer.gl.shaderSource).toHaveBeenCalledWith(
layer.fragmentShader,
"fragment"
);
});
});
describe("when typeof settings.fragmentShaderSource is a string", () => {
it("calls gl.shaderSource with it", () => {
const fragmentShaderSource = "fragment";
const layer = getGlLayer({ fragmentShaderSource });
jest.spyOn(layer.gl, "shaderSource");
layer.setupFragmentShader();
expect(layer.gl.shaderSource).toHaveBeenCalledWith(
layer.fragmentShader,
"fragment"
);
});
});
describe("when fragmentShader returns null", () => {
it("throws", () => {
const layer = getGlLayer();
jest.spyOn(layer.gl, "createShader").mockReturnValue(null);
expect(() => {
layer.setupFragmentShader();
}).toThrow();
});
});
describe("when fragmentShaderSource is undefined", () => {
it("throws", () => {
const layer = getGlLayer({ fragmentShaderSource: undefined });
expect(() => {
layer.setupFragmentShader();
}).toThrow();
});
});
it("calls gl.compileShader with fragmentShader", () => {
const layer = getGlLayer();
jest.spyOn(layer.gl, "compileShader");
layer.setupFragmentShader();
expect(layer.gl.compileShader).toBeCalledWith(layer.fragmentShader);
});
});
describe("setupProgram", () => {
describe("when setupProgram returns null", () => {
it("throws", () => {
const layer = getGlLayer();
jest.spyOn(layer.gl, "createProgram").mockReturnValue(null);
expect(() => {
layer.setupProgram();
}).toThrow();
});
});
describe("when this.vertexShader null", () => {
it("throws", () => {
const layer = getGlLayer();
expect(layer.vertexShader).toBe(null);
expect(() => {
layer.setupProgram();
}).toThrow();
});
});
describe("when this.fragmentShader null", () => {
it("throws", () => {
const layer = getGlLayer();
layer.setupVertexShader();
expect(layer.fragmentShader).toBe(null);
expect(() => {
layer.setupProgram();
}).toThrow();
});
});
it("sets this.program from gl.createProgram", () => {
const layer = getGlLayer().setupVertexShader().setupFragmentShader();
expect(layer.program).toBe(null);
layer.setupProgram();
expect(layer.program).not.toBe(null);
});
it("calls attachShader with vertexShader", () => {
const layer = getGlLayer().setupVertexShader().setupFragmentShader();
jest.spyOn(layer.gl, "attachShader");
layer.setupProgram();
expect(layer.gl.attachShader).toBeCalledWith(
layer.program,
layer.vertexShader
);
});
it("calls attachShader with fragmentShader", () => {
const layer = getGlLayer().setupVertexShader().setupFragmentShader();
jest.spyOn(layer.gl, "attachShader");
layer.setupProgram();
expect(layer.gl.attachShader).toBeCalledWith(
layer.program,
layer.fragmentShader
);
});
it("calls gl.linkProgram with program", () => {
const layer = getGlLayer().setupVertexShader().setupFragmentShader();
jest.spyOn(layer.gl, "linkProgram");
layer.setupProgram();
expect(layer.gl.linkProgram).toHaveBeenCalledWith(layer.program);
});
it("calls gl.useProgram with program", () => {
const layer = getGlLayer().setupVertexShader().setupFragmentShader();
jest.spyOn(layer.gl, "useProgram");
layer.setupProgram();
expect(layer.gl.useProgram).toHaveBeenCalledWith(layer.program);
});
it("calls gl.blendFunc with gl.SRC_ALPHA and gl.ONE_MINUS_SRC_ALPHA", () => {
const layer = getGlLayer().setupVertexShader().setupFragmentShader();
jest.spyOn(layer.gl, "blendFuncSeparate");
layer.setupProgram();
expect(layer.gl.blendFuncSeparate).toHaveBeenCalledWith(
layer.gl.SRC_ALPHA,
layer.gl.ONE_MINUS_SRC_ALPHA,
layer.gl.ONE,
layer.gl.ONE_MINUS_SRC_ALPHA
);
});
it("calls gl.enable with gl.BLEND", () => {
const layer = getGlLayer().setupVertexShader().setupFragmentShader();
jest.spyOn(layer.gl, "enable");
layer.setupProgram();
expect(layer.gl.enable).toHaveBeenCalledWith(layer.gl.BLEND);
});
});
describe("addTo", () => {
describe("when map argument is omitted", () => {
it("calls this.layer.addTo with this.map", () => {
const layer = getGlLayer();
jest.spyOn(layer.layer, "addTo");
layer.addTo();
expect(layer.layer.addTo).toHaveBeenCalledWith(layer.map);
});
});
describe("when map argument is present", () => {
it("calls this.layer.addTo with map", () => {
const element = document.createElement("div");
const map = new Map(element);
const layer = getGlLayer();
jest.spyOn(layer.layer, "addTo");
layer.addTo(map);
expect(layer.layer.addTo).toHaveBeenCalledWith(map);
});
});
it("sets this.active to true", () => {
const layer = getGlLayer();
layer.active = false;
layer.addTo();
expect(layer.active).toBe(true);
});
it("calls and returns this.render", () => {
const layer = getGlLayer();
jest.spyOn(layer, "render");
layer.addTo();
expect(layer.render).toHaveBeenCalled();
});
});
describe("remove", () => {
describe("when indices argument is undefined", () => {
it("calls this.map.removeLayer and sets this.active to false", () => {
const layer = getGlLayer();
jest.spyOn(layer.map, "removeLayer");
layer.remove();
expect(layer.map.removeLayer).toHaveBeenCalledWith(layer.layer);
expect(layer.active).toBe(false);
});
});
describe("when indices argument is a number", () => {
it("removes it from the data and calls this.render", () => {
const feature1 = {};
const feature2 = {};
const data = {
features: [feature1, feature2],
};
const layer = getGlLayer({ data });
jest.spyOn(layer, "render");
layer.remove(0);
expect(layer.data).toEqual({ features: [feature2] });
expect(layer.render).toHaveBeenCalled();
});
});
describe("when indices argument is a number[]", () => {
it("removes them from the data and calls this.render", () => {
const feature1 = {};
const feature2 = {};
const feature3 = {};
const data = {
features: [feature1, feature2, feature3],
};
const layer = getGlLayer({ data });
jest.spyOn(layer, "render");
layer.remove([0, 2]);
expect(layer.data).toEqual({ features: [feature2] });
expect(layer.render).toHaveBeenCalled();
});
});
describe("when this.settings.data is an array", () => {
it("is used, rather than this.settings.data.features", () => {
const feature1 = {};
const feature2 = {};
const data = [feature1, feature2];
const layer = getGlLayer({ data });
layer.remove(0);
expect(layer.data).toEqual([feature2]);
});
});
});
describe("insert", () => {
describe("when data has a features property", () => {
it("inserts data into defined index", () => {
const feature1 = {};
const feature2 = {};
const feature3 = {};
const data = { features: [feature1, feature3] };
const layer = getGlLayer({ data });
layer.insert(feature2, 1);
expect(layer.data).toEqual({
features: [feature1, feature2, feature3],
});
});
});
describe("when data is an array", () => {
it("inserts data into defined index", () => {
const feature1 = {};
const feature2 = {};
const feature3 = {};
const data = [feature1, feature3];
const layer = getGlLayer({ data });
layer.insert(feature2, 1);
expect(layer.data).toEqual([feature1, feature2, feature3]);
});
});
it("calls this.render()", () => {
const data = [{}];
const layer = getGlLayer({ data });
jest.spyOn(layer, "render");
layer.insert({}, 0);
expect(layer.render).toHaveBeenCalled();
});
});
describe("update", () => {
describe("when data has a features property", () => {
it("replaces data at defined index", () => {
const feature1 = {};
const feature2 = {};
const feature3 = {};
const data = { features: [feature1, feature3] };
const layer = getGlLayer({ data });
layer.update(feature2, 1);
expect(layer.data).toEqual({ features: [feature1, feature2] });
});
});
describe("when data is an array", () => {
it("replaces data at defined index", () => {
const feature1 = {};
const feature2 = {};
const feature3 = {};
const data = [feature1, feature3];
const layer = getGlLayer({ data });
layer.update(feature2, 1);
expect(layer.data).toEqual([feature1, feature2]);
});
});
it("calls this.render()", () => {
const data = [{}];
const layer = getGlLayer({ data });
jest.spyOn(layer, "render");
layer.update({}, 0);
expect(layer.render).toHaveBeenCalled();
});
});
describe("getBuffer", () => {
describe("when there is not a buffer on this.buffers with name", () => {
it("calls this.gl.createBuffer and sets it on this.buffers", () => {
const layer = getGlLayer();
expect(layer.buffers.buffer1).toBeUndefined();
jest.spyOn(layer.gl, "createBuffer");
const buffer = layer.getBuffer("buffer1");
expect(buffer).toBeTruthy();
expect(layer.gl.createBuffer).toHaveBeenCalled();
expect(layer.buffers.buffer1).toBe(buffer);
});
describe("when this.gl.createBuffer returns null", () => {
it("throws", () => {
const layer = getGlLayer();
jest.spyOn(layer.gl, "createBuffer").mockReturnValue(null);
expect(() => {
layer.getBuffer("buffer1");
}).toThrow();
});
});
});
describe("when there is not a buffer on this.buffers with name", () => {
it("returns this.buffers with name", () => {
const layer = getGlLayer();
jest.spyOn(layer.gl, "createBuffer");
layer.buffers.buffer1 = new WebGLBuffer();
const buffer = layer.getBuffer("buffer1");
expect(buffer).toBe(layer.buffers.buffer1);
expect(layer.gl.createBuffer).not.toHaveBeenCalled();
});
});
});
describe("getAttributeLocation", () => {
describe("when this.program is null", () => {
it("throws", () => {
const layer = getGlLayer();
expect(layer.program).toBe(null);
expect(() => {
layer.getAttributeLocation("attribute1");
}).toThrow();
});
});
describe("when this.attributeLocations[name] is not defined", () => {
it("sets this.attributeLocations[name] and returns the attributeLocation", () => {
const layer = getGlLayer();
layer.program = new WebGLProgram();
expect(layer.attributeLocations.attribute1).toBeUndefined();
jest.spyOn(layer.gl, "getAttribLocation");
const attribute = layer.getAttributeLocation("attribute1");
expect(attribute).toBeTruthy();
expect(layer.gl.getAttribLocation).toHaveBeenCalledWith(
layer.program,
"attribute1"
);
expect(layer.attributeLocations.attribute1).toBe(attribute);
});
});
});
describe("getUniformLocation", () => {
describe("when this.program is null", () => {
it("throws", () => {
const layer = getGlLayer();
expect(layer.program).toBe(null);
expect(() => {
layer.getUniformLocation("uniformLocation1");
}).toThrow();
});
});
describe("when this.uniformLocations[name] is not defined", () => {
it("sets this.uniformLocations[name] and returns the uniformLocation", () => {
const layer = getGlLayer();
layer.program = new WebGLProgram();
expect(layer.uniformLocations.uniformLocation1).toBeUndefined();
jest.spyOn(layer.gl, "getUniformLocation");
const uniformLocation = layer.getUniformLocation("uniformLocation1");
expect(uniformLocation).not.toBeFalsy();
expect(layer.gl.getUniformLocation).toHaveBeenCalledWith(
layer.program,
"uniformLocation1"
);
expect(layer.uniformLocations.uniformLocation1).toBe(uniformLocation);
});
});
describe("when this.gl.getUniformLocation returns null", () => {
it("throws", () => {
const layer = getGlLayer();
jest.spyOn(layer.gl, "getUniformLocation").mockReturnValue(null);
expect(() => {
layer.getUniformLocation("uniformLocation1");
}).toThrow();
});
});
});
describe("click", () => {
describe("when this.settings.click is undefined", () => {
it("does not throw", () => {
const layer = getGlLayer();
expect(layer.settings.click).toBeUndefined();
expect(() => {
layer.click(fakeEvent(layer), {});
}).not.toThrow();
});
});
describe("when this.settings.click is defined", () => {
describe("when it does not return a value", () => {
it("calls this.settings.click and returns void", () => {
const click = jest.fn(() => {
return undefined;
});
const layer = getGlLayer({ click });
const event = fakeEvent(layer);
const feature = {};
const result = layer.click(event, feature);
expect(click).toHaveBeenCalledWith(event, feature);
expect(result).toBeUndefined();
});
});
describe("when it does return a value", () => {
it("calls this.settings.click and returns void", () => {
const click = jest.fn(() => {
return true;
});
const layer = getGlLayer({ click });
const event = fakeEvent(layer);
const feature = {};
const result = layer.click(event, feature);
expect(click).toHaveBeenCalledWith(event, feature);
expect(result).toBeTruthy();
});
});
});
});
describe("hover", () => {
describe("when this.settings.hover is undefined", () => {
it("does not throw", () => {
const layer = getGlLayer();
expect(layer.settings.hover).toBeUndefined();
expect(() => {
layer.hover(fakeEvent(layer), {});
}).not.toThrow();
});
});
describe("when this.settings.hover is defined", () => {
describe("when it does not return a value", () => {
it("calls this.settings.hover and returns void", () => {
const hover = jest.fn(() => {
return undefined;
});
const layer = getGlLayer({ hover });
const event = fakeEvent(layer);
const feature = {};
const result = layer.hover(event, feature);
expect(hover).toHaveBeenCalledWith(event, feature);
expect(result).toBeUndefined();
});
});
describe("when it does return a value", () => {
it("calls this.settings.hover and returns void", () => {
const hover = jest.fn(() => {
return true;
});
const layer = getGlLayer({ hover });
const feature = {};
const event = fakeEvent(layer);
const result = layer.hover(event, feature);
expect(hover).toHaveBeenCalledWith(event, feature);
expect(result).toBeTruthy();
});
});
});
});
describe("hoverOff", () => {
describe("when this.settings.hoverOff is undefined", () => {
it("does not throw", () => {
const layer = getGlLayer();
expect(layer.settings.hoverOff).toBeUndefined();
expect(() => {
layer.hover(fakeEvent(layer), {});
}).not.toThrow();
});
});
describe("when this.settings.hoverOff is defined", () => {
describe("when it does not return a value", () => {
it("calls this.settings.hoverOff and returns void", () => {
const hoverOff = jest.fn(() => {
return undefined;
});
const layer = getGlLayer({ hoverOff });
const event = fakeEvent(layer);
const feature = {};
layer.hoverOff(event, feature);
expect(hoverOff).toHaveBeenCalledWith(event, feature);
});
});
});
});
});