UNPKG

terriajs

Version:

Geospatial data visualization platform.

345 lines (299 loc) 13.5 kB
import { action, runInAction } from "mobx"; import Cartesian3 from "terriajs-cesium/Source/Core/Cartesian3"; import queryToObject from "terriajs-cesium/Source/Core/queryToObject"; import Entity from "terriajs-cesium/Source/DataSources/Entity"; import SplitDirection from "terriajs-cesium/Source/Scene/SplitDirection"; import URI from "urijs"; import { USER_ADDED_CATEGORY_ID } from "../../../../../lib/Core/addedByUser"; import PickedFeatures from "../../../../../lib/Map/PickedFeatures/PickedFeatures"; import addUserCatalogMember from "../../../../../lib/Models/Catalog/addUserCatalogMember"; import GeoJsonCatalogItem from "../../../../../lib/Models/Catalog/CatalogItems/GeoJsonCatalogItem"; import WebMapServiceCatalogItem from "../../../../../lib/Models/Catalog/Ows/WebMapServiceCatalogItem"; import CommonStrata from "../../../../../lib/Models/Definition/CommonStrata"; import { BaseModel } from "../../../../../lib/Models/Definition/Model"; import TerriaFeature from "../../../../../lib/Models/Feature/Feature"; import { InitSourceData } from "../../../../../lib/Models/InitSource"; import Terria from "../../../../../lib/Models/Terria"; import { setViewerMode } from "../../../../../lib/Models/ViewerMode"; import ViewState from "../../../../../lib/ReactViewModels/ViewState"; import { buildShareLink, isShareable, SHARE_VERSION } from "../../../../../lib/ReactViews/Map/Panels/SharePanel/BuildShareLink"; import bikeRacksGeoJson from "../../../../../wwwroot/test/GeoJSON/bike_racks.geojson" with { type: "json" }; let terria: Terria; let viewState: ViewState; beforeEach(function () { terria = new Terria({ baseUrl: "./" }); // terria.baseMap = { // name: "Bing Maps Aerial" // }; viewState = new ViewState({ terria: terria, catalogSearchProvider: undefined }); }); const decodeAndParseStartHash = (url: string) => { const parsed = URI.parse(url); if (parsed.fragment) { return JSON.parse(queryToObject(parsed.fragment)["start"]); } }; const flattenInitSources = (initSources: InitSourceData[]): InitSourceData => initSources.reduce( (acc: InitSourceData, initSource: InitSourceData) => Object.assign(acc, initSource), {} ); describe("BuildShareLink", function () { it("should generate a url with default catalog related flags missing/undefined", function () { const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); expect(params.version).toBe(SHARE_VERSION); expect(initSources.previewedItemId).toBeUndefined(); }); describe("user added model containing local data", function () { it("should not be serialized", async function () { const modelId = "Test"; const model = new GeoJsonCatalogItem(modelId, terria); const blob = new Blob([JSON.stringify(bikeRacksGeoJson)], { type: "application/json" }); model.setFileInput(blob as File); terria.addModel(model); expect(terria.getModelById(BaseModel, modelId)).toBe(model); expect(isShareable(terria)(modelId)).toBe(false); await addUserCatalogMember(terria, model); const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); expect( initSources.models?.[USER_ADDED_CATEGORY_ID].members ).not.toContain(model.uniqueId); }); it("should not be added to workbench in generated url", async function () { const modelId = "Test"; const model = new GeoJsonCatalogItem(modelId, terria); const blob = new Blob([JSON.stringify(bikeRacksGeoJson)], { type: "application/json" }); model.setFileInput(blob as File); terria.addModel(model); await addUserCatalogMember(terria, model); await terria.workbench.add(model); const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); expect(initSources.workbench).not.toContain(model.uniqueId); }); }); describe("user added model containing no local data", function () { let model: BaseModel; beforeEach(function () { model = new WebMapServiceCatalogItem("Test", terria); runInAction(() => { model.setTrait( CommonStrata.definition, "url", "test/WMS/single_metadata_url.xml" ); }); terria.addModel(model); }); it("should be serialized", async function () { await addUserCatalogMember(terria, model); const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); expect(model.uniqueId).toBeDefined(); expect(isShareable(terria)(model.uniqueId ?? "")).toBe(true); expect(initSources.models?.[USER_ADDED_CATEGORY_ID].members).toContain( model.uniqueId ); }); it("should be added to workbench in generated url", async function () { await addUserCatalogMember(terria, model); await terria.workbench.add(model); const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); expect(initSources.workbench).toContain(model.uniqueId); }); }); describe("should generate a url that opens to the catalog", function () { beforeEach(function () { terria.catalog.userAddedDataGroup.addMembersFromJson(CommonStrata.user, [ { id: "ABC", name: "abc", type: "wms", url: "test/WMS/single_metadata_url.xml" } ]); }); // sharing active tab category not implemented in mobx yet // it("when the explorer window is open without a previewed catalog item", function() { // viewState.openAddData(); // const shareLink = buildShareLink(terria, viewState); // const params = decodeAndParseStartHash(shareLink); // const initSources = flattenInitSources(params.initSources); // expect(initSources.previewedItemId).toBe(undefined); // // expect(initSources.sharedFromExplorerPanel).toBe(true); // // expect(viewState.activeTabCategory).toBe(DATA_CATALOG_NAME); // }); describe("opening to the user added tab", function () { // below case is impossible with the UI at the moment, but we might want to // share the 'empty-user-catalog-as-drag-and-drop' state in the future // it("without a previewed item", function() { // viewState.openUserData(); // const shareLink = buildShareLink(terria, viewState); // const params = decodeAndParseStartHash(shareLink); // const initSources = flattenInitSources(params.initSources); // expect(initSources.previewedItemId).toBe(undefined); // // expect(initSources.sharedFromExplorerPanel).toBe(true); // // expect(viewState.activeTabCategory).toBe(USER_DATA_NAME); // }); it("viewing a previewed item", async function () { const model = terria.catalog.userAddedDataGroup.memberModels[0]; // preview the user added item & the share link should reflect that await viewState.viewCatalogMember(model); const shareLink = buildShareLink(terria, viewState); let params = decodeAndParseStartHash(shareLink); let initSources = flattenInitSources(params.initSources); expect(initSources.previewedItemId).toBe(model.uniqueId); // close the catalog & the share link should reflect that viewState.closeCatalog(); params = decodeAndParseStartHash(buildShareLink(terria, viewState)); initSources = flattenInitSources(params.initSources); expect(initSources.previewedItemId).toBeUndefined(); }); }); }); describe("sharing picked features", function () { it( "captures the picked position", action(function () { terria.pickedFeatures = new PickedFeatures(); terria.pickedFeatures.pickPosition = new Cartesian3( 17832.12, 83234.52, 952313.73 ); terria.pickedFeatures.features.push(new TerriaFeature({})); const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); const pickCoords = initSources.pickedFeatures?.pickCoords; expect(pickCoords?.lat.toFixed(2)).toEqual("84.93"); expect(pickCoords?.lng.toFixed(2)).toEqual("77.91"); expect(pickCoords?.height.toFixed(2)).toEqual("-5400810.41"); }) ); it( "captures the tile coordinates of the picked imagery providers", action(function () { terria.pickedFeatures = new PickedFeatures(); terria.pickedFeatures.pickPosition = new Cartesian3( 17832.12, 83234.52, 952313.73 ); terria.pickedFeatures.providerCoords = { "https://foo": { x: 123, y: 456, level: 7 }, "https://bar": { x: 42, y: 42, level: 4 } }; terria.pickedFeatures.features.push(new TerriaFeature({})); const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); const providerCoords = initSources.pickedFeatures?.providerCoords; expect(providerCoords).toEqual({ "https://foo": { x: 123, y: 456, level: 7 }, "https://bar": { x: 42, y: 42, level: 4 } }); }) ); it( "captures the selected feature", action(function () { terria.pickedFeatures = new PickedFeatures(); terria.pickedFeatures.pickPosition = new Cartesian3( 17832.12, 83234.52, 952313.73 ); const feature = new Entity({ name: "testFeature" }) as TerriaFeature; terria.pickedFeatures.features.push(feature); terria.selectedFeature = feature; const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); const current = initSources.pickedFeatures?.current; expect(current?.name).toEqual("testFeature"); expect(current?.hash).toBeDefined(); }) ); it( "captures all picked vector features", action(function () { terria.pickedFeatures = new PickedFeatures(); terria.pickedFeatures.pickPosition = new Cartesian3( 17832.12, 83234.52, 952313.73 ); terria.pickedFeatures.features.push( new TerriaFeature({ name: "testFeature1" }) ); terria.pickedFeatures.features.push( new TerriaFeature({ name: "testFeature2" }) ); const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); const entities = initSources.pickedFeatures?.entities; expect(entities?.[0].name).toEqual("testFeature1"); expect(entities?.[0].hash).toBeDefined(); expect(entities?.[1].name).toEqual("testFeature2"); expect(entities?.[1].hash).toBeDefined(); }) ); }); describe("map settings", function () { it("serialises correctly", async function () { const testBaseMap = new GeoJsonCatalogItem( "test-basemap", terria, undefined ); testBaseMap.setTrait( CommonStrata.definition, "geoJsonString", `{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[145.5908203125,-40.17887331434695],[143.349609375,-42.08191667830631],[146.35986328124997,-44.040218713142124],[149.08447265625,-42.859859815062784],[148.55712890625,-41.36031866306708],[145.5908203125,-40.17887331434695]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[75.9375,51.069016659603896],[59.94140624999999,39.095962936305476],[79.453125,42.032974332441405],[80.15625,46.800059446787316],[75.673828125,51.45400691005982],[75.9375,51.069016659603896]]]}}]}` ); terria.setBaseMaximumScreenSpaceError(1); terria.setUseNativeResolution(true); setViewerMode("2d", terria.mainViewer); terria.timelineStack.setAlwaysShowTimeline(true); await terria.mainViewer.setBaseMap(testBaseMap); terria.terrainSplitDirection = SplitDirection.LEFT; terria.depthTestAgainstTerrainEnabled = true; const shareLink = buildShareLink(terria, viewState); const params = decodeAndParseStartHash(shareLink); const initSources = flattenInitSources(params.initSources); expect(initSources.viewerMode).toBe("2d"); expect(initSources.settings).toEqual({ baseMaximumScreenSpaceError: 1, useNativeResolution: true, alwaysShowTimeline: true, baseMapId: "test-basemap", terrainSplitDirection: -1, depthTestAgainstTerrainEnabled: true }); }); }); });