UNPKG

@panoramax/web-viewer

Version:

Panoramax web viewer for geolocated pictures

444 lines (401 loc) 12.9 kB
import URLHandler from "../../src/utils/URLHandler"; describe("listenToChanges", () => { it("should add event listeners to window, parent, psv, and map", () => { window.addEventListener = jest.fn(); const parent = { addEventListener: jest.fn(), psv: { addEventListener: jest.fn() }, map: { on: jest.fn() }, }; const urlHandler = new URLHandler(parent); urlHandler.listenToChanges(); expect(window.addEventListener).toHaveBeenCalledWith("popstate", expect.any(Function), false); ["focus-changed", "pictures-navigation-changed"].forEach(event => { expect(parent.addEventListener).toHaveBeenCalledWith(event, expect.any(Function)); }); ["position-updated", "zoom-updated", "view-rotated", "picture-loaded", "transition-duration-changed"].forEach(event => { expect(parent.psv.addEventListener).toHaveBeenCalledWith(event, expect.any(Function)); }); ["moveend", "zoomend", "boxzoomend", "background-changed", "users-changed", "filters-changed"].forEach(event => { expect(parent.map.on).toHaveBeenCalledWith(event, expect.any(Function)); }); }); }); describe("nextURLString", () => { it("works without any specific values set", () => { const v = { addEventListener: jest.fn(), psv: { getPicturesNavigation: () => null, getTransitionDuration: () => null, getPictureMetadata: () => null, getPictureId: () => null, }, }; const uh = new URLHandler(v); expect(uh.nextURLString()).toBe("?"); }); it("works with picture metadata", () => { const v = { addEventListener: jest.fn(), psv: { getPicturesNavigation: () => null, getTransitionDuration: () => null, getPictureMetadata: () => ({}), getPictureId: () => "cbfc3add-8173-4464-98c8-de2a43c6a50f", }, }; const uh = new URLHandler(v); uh.currentPSVString = () => "0/1/2"; expect(uh.nextURLString()).toBe("?pic=cbfc3add-8173-4464-98c8-de2a43c6a50f&xyz=0/1/2"); }); it("works with map started + wide", () => { const v = { addEventListener: jest.fn(), psv: { getPicturesNavigation: () => null, getTransitionDuration: () => null, getPictureMetadata: () => null, getPictureId: () => null, }, map: { getVisibleUsers: () => ["geovisio"], hasTwoBackgrounds: () => false, loaded: () => true, }, isMapWide: () => true, popup: { hasAttribute: () => false }, }; const uh = new URLHandler(v); uh.currentMapString = () => "18/0.5/-12"; expect(uh.nextURLString()).toBe("?focus=map&map=18/0.5/-12"); }); it("works with map + picture wide", () => { const v = { addEventListener: jest.fn(), psv: { getPicturesNavigation: () => null, getTransitionDuration: () => null, getPictureMetadata: () => ({}), getPictureId: () => "cbfc3add-8173-4464-98c8-de2a43c6a50f", }, map: { getVisibleUsers: () => ["geovisio"], hasTwoBackgrounds: () => false, loaded: () => true, }, isMapWide: () => false, popup: { hasAttribute: () => false }, }; const uh = new URLHandler(v); uh.currentPSVString = () => "0/1/2"; uh.currentMapString = () => "18/0.5/-12"; expect(uh.nextURLString()).toBe("?focus=pic&map=18/0.5/-12&pic=cbfc3add-8173-4464-98c8-de2a43c6a50f&xyz=0/1/2"); }); it("works with map filters", () => { const v = { addEventListener: jest.fn(), psv: { getPicturesNavigation: () => null, getTransitionDuration: () => null, getPictureMetadata: () => null, getPictureId: () => null, }, map: { getVisibleUsers: () => ["geovisio"], hasTwoBackgrounds: () => false, loaded: () => true, _mapFilters: { "minDate": "2023-01-01", "maxDate": "2023-08-08", "camera": "sony", "pic_type": "flat", "theme": "age", }, }, isMapWide: () => false, popup: { hasAttribute: () => false }, }; const uh = new URLHandler(v); uh.currentMapString = () => "18/0.5/-12"; expect(uh.nextURLString()).toBe("?camera=sony&date_from=2023-01-01&date_to=2023-08-08&focus=pic&map=18/0.5/-12&pic_type=flat&theme=age"); }); it("works with speed", () => { const v = { addEventListener: jest.fn(), psv: { getPicturesNavigation: () => null, getTransitionDuration: () => 250, getPictureMetadata: () => null, getPictureId: () => null, }, }; const uh = new URLHandler(v); expect(uh.nextURLString()).toBe("?speed=250"); }); it("works with popup", () => { const v = { addEventListener: jest.fn(), psv: { getPicturesNavigation: () => null, getTransitionDuration: () => null, getPictureMetadata: () => null, getPictureId: () => null, }, map: { getVisibleUsers: () => ["geovisio"], hasTwoBackgrounds: () => false, loaded: () => true, }, isMapWide: () => false, popup: { hasAttribute: () => true }, }; const uh = new URLHandler(v); uh.currentMapString = () => "18/0.5/-12"; expect(uh.nextURLString()).toBe("?focus=pic&map=18/0.5/-12"); }); it("works with nav", () => { const v = { addEventListener: jest.fn(), psv: { getPicturesNavigation: () => "pic", getTransitionDuration: () => null, getPictureMetadata: () => null, getPictureId: () => null, }, }; const uh = new URLHandler(v); expect(uh.nextURLString()).toBe("?nav=pic"); }); }); describe("currentURLParams", () => { it("works if empty + search", () => { delete window.location; window.location = { search: "" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams()).toStrictEqual({}); }); it("works with single param + search", () => { delete window.location; window.location = { search: "?nav=pic" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams()).toStrictEqual({"nav": "pic"}); }); it("works with multiple params + search", () => { delete window.location; window.location = { search: "?nav=pic&speed=42" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams()).toStrictEqual({"nav": "pic", "speed": "42"}); }); it("works if empty + hash", () => { delete window.location; window.location = { hash: "" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams(true)).toStrictEqual({}); }); it("works with single param + hash", () => { delete window.location; window.location = { hash: "#nav=pic" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams(true)).toStrictEqual({"nav": "pic"}); }); it("works with multiple params + hash", () => { delete window.location; window.location = { hash: "#nav=pic&speed=42" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams(true)).toStrictEqual({"nav": "pic", "speed": "42"}); }); it("works with search + hash", () => { delete window.location; window.location = { hash: "#nav=pic&speed=42", search: "?pic=bla" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams()).toStrictEqual({"pic": "bla"}); expect(uh.currentURLParams(true)).toStrictEqual({"nav": "pic", "speed": "42"}); }); it("skips unmanaged parameters", () => { delete window.location; window.location = { search: "?a=b" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams()).toStrictEqual({}); }); it("works with shortlinks", () => { delete window.location; window.location = { search: "?s=fp;s2;pa0270208-d79d-49a9-85c7-a352bb96962e;c282.09/9.34/30;m17/43.107492/5.868459;va;bs" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams()).toStrictEqual({ "focus": "pic", "speed": 200, "pic": "a0270208-d79d-49a9-85c7-a352bb96962e", "xyz": "282.09/9.34/30", "map": "17/43.107492/5.868459", "theme": "age", "background": "streets", "camera": undefined, "date_from": undefined, "date_to": undefined, "pic_score": undefined, "users": undefined }); }); it("works with shortlinks urlEncoded", () => { delete window.location; window.location = { search: "?s=fp%3Bs2%3Bpa0270208-d79d-49a9-85c7-a352bb96962e%3Bc282.09/9.34/30%3Bm17/43.107492/5.868459%3Bva%3Bbs" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); expect(uh.currentURLParams()).toStrictEqual({ "focus": "pic", "speed": 200, "pic": "a0270208-d79d-49a9-85c7-a352bb96962e", "xyz": "282.09/9.34/30", "map": "17/43.107492/5.868459", "theme": "age", "background": "streets", "camera": undefined, "date_from": undefined, "date_to": undefined, "pic_score": undefined, "users": undefined }); }); }); describe("currentMapString", () => { it("works with zoom+center", () => { const v = { addEventListener: jest.fn(), map: { getZoom: () => 18, getCenter: () => ({ lng: -12.5, lat: 48.75 }), getBearing: () => null, getPitch: () => null, } }; const uh = new URLHandler(v); expect(uh.currentMapString()).toBe("18/48.75/-12.5"); }); it("works with zoom+center+bearing", () => { const v = { addEventListener: jest.fn(), map: { getZoom: () => 18, getCenter: () => ({ lng: -12.5, lat: 48.75 }), getBearing: () => 12, getPitch: () => null, } }; const uh = new URLHandler(v); expect(uh.currentMapString()).toBe("18/48.75/-12.5/12"); }); it("works with zoom+center+pitch", () => { const v = { addEventListener: jest.fn(), map: { getZoom: () => 18, getCenter: () => ({ lng: -12.5, lat: 48.75 }), getBearing: () => null, getPitch: () => 65, }, }; const uh = new URLHandler(v); expect(uh.currentMapString()).toBe("18/48.75/-12.5/0/65"); }); it("works with zoom+center+bearing+pitch", () => { const v = { addEventListener: jest.fn(), map: { getZoom: () => 18, getCenter: () => ({ lng: -12.5, lat: 48.75 }), getBearing: () => 42, getPitch: () => 65, }, }; const uh = new URLHandler(v); expect(uh.currentMapString()).toBe("18/48.75/-12.5/42/65"); }); }); describe("currentPSVString", () => { it("works", () => { const v = { addEventListener: jest.fn(), psv: { getXYZ: () => ({ x: 12, y: 50, z: 75 }), }, }; const uh = new URLHandler(v); expect(uh.currentPSVString()).toBe("12.00/50.00/75"); }); it("rounds to 2 decimals", () => { const v = { addEventListener: jest.fn(), psv: { getXYZ: () => ({ x: 12.123456, y: 50.789456, z: 75 }), getPictureId: () => null, }, }; const uh = new URLHandler(v); expect(uh.currentPSVString()).toBe("12.12/50.79/75"); }); it("works without z", () => { const v = { addEventListener: jest.fn(), psv: { getXYZ: () => ({ x: 12, y: 50 }), getPictureId: () => null, }, }; const uh = new URLHandler(v); expect(uh.currentPSVString()).toBe("12.00/50.00/0"); }); }); describe("_onParentChange", () => { it("works", async () => { delete window.history; delete window.location; window.history = { replaceState: jest.fn(), state: {} }; window.location = { href: "http://localhost:5000/?nav=pic&speed=2", search: "?nav=pic&speed=2", hash: "" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); uh.nextURLString = () => "?map=1/2/3"; uh.dispatchEvent = jest.fn(); uh._onParentChange(); await new Promise((r) => setTimeout(r, 1000)); expect(window.history.replaceState.mock.calls.pop()).toEqual([{}, null, "http://localhost:5000/?map=1/2/3"]); expect(uh.dispatchEvent.mock.calls).toMatchSnapshot(); }); it("works with pic change", async () => { delete window.history; delete window.location; window.history = { pushState: jest.fn(), state: {} }; window.location = { href: "http://localhost:5000/?pic=bla", search: "?pic=bla", hash: "" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); uh.nextURLString = () => "?nav=seq"; uh.dispatchEvent = jest.fn(); uh._onParentChange(); await new Promise((r) => setTimeout(r, 1000)); expect(window.history.pushState.mock.calls.pop()).toEqual([{}, null, "http://localhost:5000/?nav=seq"]); expect(uh.dispatchEvent.mock.calls).toMatchSnapshot(); }); it("deduplicates calls", async () => { delete window.history; delete window.location; window.history = { replaceState: jest.fn(), state: {} }; window.location = { href: "http://localhost:5000/?speed=1&nav=seq", search: "?speed=1&nav=seq", hash: "" }; const v = { addEventListener: jest.fn() }; const uh = new URLHandler(v); uh.nextURLString = () => "?map=1/2/3"; for(let i=0; i <= 10; i++) { uh._onParentChange(); } await new Promise((r) => setTimeout(r, 1000)); expect(window.history.replaceState.mock.calls).toEqual([[{}, null, "http://localhost:5000/?map=1/2/3"]]); }); });