UNPKG

terriajs

Version:

Geospatial data visualization platform.

1,453 lines (1,287 loc) 73.2 kB
import { http, HttpResponse } from "msw"; import { runInAction } from "mobx"; import JulianDate from "terriajs-cesium/Source/Core/JulianDate"; import CustomDataSource from "terriajs-cesium/Source/DataSources/CustomDataSource"; import LabelStyle from "terriajs-cesium/Source/Scene/LabelStyle"; import { getMakiIcon } from "../../lib/Map/Icons/Maki/MakiIcons"; import { ImageryParts } from "../../lib/ModelMixins/MappableMixin"; import CsvCatalogItem from "../../lib/Models/Catalog/CatalogItems/CsvCatalogItem"; import CommonStrata from "../../lib/Models/Definition/CommonStrata"; import createStratumInstance from "../../lib/Models/Definition/createStratumInstance"; import updateModelFromJson from "../../lib/Models/Definition/updateModelFromJson"; import TerriaFeature from "../../lib/Models/Feature/Feature"; import { TerriaFeatureData } from "../../lib/Models/Feature/FeatureData"; import Terria from "../../lib/Models/Terria"; import { worker } from "../mocks/browser"; import TableColorStyleTraits from "../../lib/Traits/TraitsClasses/Table/ColorStyleTraits"; import TableLabelStyleTraits, { EnumLabelSymbolTraits, LabelSymbolTraits } from "../../lib/Traits/TraitsClasses/Table/LabelStyleTraits"; import TableOutlineStyleTraits, { BinOutlineSymbolTraits, EnumOutlineSymbolTraits } from "../../lib/Traits/TraitsClasses/Table/OutlineStyleTraits"; import TablePointStyleTraits, { BinPointSymbolTraits, EnumPointSymbolTraits, PointSymbolTraits } from "../../lib/Traits/TraitsClasses/Table/PointStyleTraits"; import TableStyleTraits from "../../lib/Traits/TraitsClasses/Table/StyleTraits"; import TableTimeStyleTraits from "../../lib/Traits/TraitsClasses/Table/TimeStyleTraits"; import TableTrailStyleTraits, { BinTrailSymbolTraits, EnumTrailSymbolTraits } from "../../lib/Traits/TraitsClasses/Table/TrailStyleTraits"; import HorizontalOrigin from "terriajs-cesium/Source/Scene/HorizontalOrigin"; import VerticalOrigin from "terriajs-cesium/Source/Scene/VerticalOrigin"; import ScaleByDistanceTraits from "../../lib/Traits/TraitsClasses/ScaleByDistanceTraits"; import LatLonValCsv from "../../wwwroot/test/csv/lat_lon_val.csv"; import LatLonEnumCsv from "../../wwwroot/test/csv/lat_lon_enum.csv"; import LatLonValCsvDuplicate from "../../wwwroot/test/csv/lat_lon_val_with_duplicate_row.csv"; import LatLonEnumDateIdCsv from "../../wwwroot/test/csv/lat_lon_enum_date_id.csv"; import LatLonEnumDateIdWithRegionCsv from "../../wwwroot/test/csv/lat_lon_enum_date_id_with_regions.csv"; import LgaWithDisambigCsv from "../../wwwroot/test/csv/lga_state_disambig.csv"; import ParkingSensorDataCsv from "../../wwwroot/test/csv/parking-sensor-data.csv"; import LegendDecimalPlacesCsv from "../../wwwroot/test/csv/legend-decimal-places.csv"; import BadDatesCsv from "../../wwwroot/test/csv/bad-dates.csv"; import regionMapping from "../../wwwroot/data/regionMapping.json"; import additionalRegionMapping from "../../wwwroot/test/regionMapping/additionalRegion.json"; import regionIdsSte from "../../wwwroot/data/regionids/region_map-STE_2016_AUST_STE_NAME16.json"; import regionIdsLgaName from "../../wwwroot/data/regionids/region_map-FID_LGA_2011_AUST_LGA_NAME11.json"; import regionIdsLgaCode from "../../wwwroot/data/regionids/region_map-FID_LGA_2015_AUST_LGA_CODE15.json"; import regionIdsLgaNameStates from "../../wwwroot/data/regionids/region_map-FID_LGA_2011_AUST_STE_NAME11.json"; const NUMBER_OF_REGION_MAPPING_TYPES = 154; describe("TableMixin", function () { let item: CsvCatalogItem; let terria: Terria; beforeEach(function () { terria = new Terria({ baseUrl: "./" }); item = new CsvCatalogItem("test", terria, undefined); worker.use( http.get("*/build/TerriaJS/data/regionMapping.json", () => HttpResponse.json(regionMapping) ), http.get( "https://tiles.terria.io/region-mapping/regionids/region_map-STE_2016_AUST_STE_NAME16.json", () => HttpResponse.json(regionIdsSte) ), http.get( "https://tiles.terria.io/region-mapping/regionids/region_map-FID_LGA_2011_AUST_LGA_NAME11.json", () => HttpResponse.json(regionIdsLgaName) ), http.get( "https://tiles.terria.io/region-mapping/regionids/region_map-FID_LGA_2015_AUST_LGA_CODE15.json", () => HttpResponse.json(regionIdsLgaCode) ), http.get( "https://tiles.terria.io/region-mapping/regionids/region_map-FID_LGA_2011_AUST_STE_NAME11.json", () => HttpResponse.json(regionIdsLgaNameStates) ) ); }); describe("when the table has time, lat/lon and id columns", function () { let dataSource: CustomDataSource; beforeEach(async function () { item.setTrait(CommonStrata.user, "csvString", LatLonEnumDateIdCsv); (await item.loadMapItems()).throwIfError(); dataSource = item.mapItems[0] as CustomDataSource; expect(dataSource instanceof CustomDataSource).toBe(true); }); it("creates one entity per id", function () { expect(item.activeTableStyle.rowGroups.length).toBe(4); if (dataSource instanceof CustomDataSource) { expect(dataSource.entities.values.length).toBe(4); } }); it("sets showInChartPanel to false - as is mappable", function () { expect(item.showInChartPanel).toBeFalsy(); }); it("sets showInChartPanel to true - when lat/lon is disabled", function () { updateModelFromJson(item, CommonStrata.definition, { columns: [ { name: "lat", type: "scalar" }, { name: "lon", type: "scalar" } ] }); expect(item.showInChartPanel).toBeTruthy(); }); it("doesn't show regions - even if empty region column is detected", () => {}); it("calculates rectangle", function () { expect(item.rectangle.north).toEqual(-20); expect(item.rectangle.south).toEqual(-37); expect(item.rectangle.east).toEqual(155); expect(item.rectangle.west).toEqual(115); }); describe("the entities", function () { it("has availability defined over the correct span", function () { expect( dataSource.entities.values.map((e) => e.availability?.start.toString() ) ).toEqual([ "2015-08-01T00:00:00Z", "2015-08-01T00:00:00Z", "2015-08-02T00:00:00Z", "2015-08-03T00:00:00Z" ]); expect( dataSource.entities.values.map((e) => e.availability?.stop.toString()) ).toEqual([ "2015-08-07T06:00:00Z", "2015-08-07T00:00:00Z", "2015-08-02T23:59:59Z", "2015-08-05T00:00:00Z" ]); }); }); describe("when timeColumn is `null`", function () { it("returns an empty `discreteTimes`", function () { expect(item.discreteTimes?.length).toBe(6); item.defaultStyle.time.setTrait(CommonStrata.user, "timeColumn", null); expect(item.discreteTimes).toBe(undefined); }); it("creates entities for all times", async function () { item.defaultStyle.time.setTrait(CommonStrata.user, "timeColumn", null); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0]; expect(mapItem instanceof CustomDataSource).toBe(true); if (mapItem instanceof CustomDataSource) { expect(mapItem.entities.values.length).toBe(13); } }); }); }); // Note this is identical to "when the table has time, lat/lon and id columns" EXCEPT // - one additional spec - "doesn't show regions - even if empty region column is detected" // - "sets showInChartPanel to true - when lat/lon is disabled" is replaced by "shows regions when lat/lon is disabled" describe("when the table has time, lat/lon, id columns AND regions", function () { let dataSource: CustomDataSource; beforeEach(async function () { item.setTrait( CommonStrata.user, "csvString", LatLonEnumDateIdWithRegionCsv ); (await item.loadMapItems()).throwIfError(); dataSource = item.mapItems[0] as CustomDataSource; expect(dataSource instanceof CustomDataSource).toBe(true); }); it("creates one entity per id", function () { expect(item.activeTableStyle.rowGroups.length).toBe(4); if (dataSource instanceof CustomDataSource) { expect(dataSource.entities.values.length).toBe(4); } }); it("sets showInChartPanel to false - as is mappable", function () { expect(item.showInChartPanel).toBeFalsy(); }); it("shows regions when lat/lon is disabled", function () { updateModelFromJson(item, CommonStrata.definition, { columns: [ { name: "lat", type: "scalar" }, { name: "lon", type: "scalar" } ] }); expect(item.showInChartPanel).toBeFalsy(); expect(item.showingRegions).toBeTruthy(); expect( item.activeTableStyle.regionColumn?.valuesAsRegions.uniqueRegionIds .length ).toBe(3); }); it("doesn't show regions - as more points are detected than unique regions", () => { expect(item.showingRegions).toBeFalsy(); }); it("calculates rectangle", function () { expect(item.rectangle.north).toEqual(-20); expect(item.rectangle.south).toEqual(-37); expect(item.rectangle.east).toEqual(155); expect(item.rectangle.west).toEqual(115); }); describe("the entities", function () { it("has availability defined over the correct span", function () { expect( dataSource.entities.values.map((e) => e.availability?.start.toString() ) ).toEqual([ "2015-08-01T00:00:00Z", "2015-08-01T00:00:00Z", "2015-08-02T00:00:00Z", "2015-08-03T00:00:00Z" ]); expect( dataSource.entities.values.map((e) => e.availability?.stop.toString()) ).toEqual([ "2015-08-07T06:00:00Z", "2015-08-07T00:00:00Z", "2015-08-02T23:59:59Z", "2015-08-05T00:00:00Z" ]); }); }); describe("when timeColumn is `null`", function () { it("returns an empty `discreteTimes`", function () { expect(item.discreteTimes?.length).toBe(6); item.defaultStyle.time.setTrait(CommonStrata.user, "timeColumn", null); expect(item.discreteTimes).toBe(undefined); }); it("creates entities for all times", async function () { item.defaultStyle.time.setTrait(CommonStrata.user, "timeColumn", null); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0]; expect(mapItem instanceof CustomDataSource).toBe(true); if (mapItem instanceof CustomDataSource) { expect(mapItem.entities.values.length).toBe(13); } }); }); }); describe("when the table has lat/lon columns but no time & id columns", function () { it("creates one entity per row", async function () { runInAction(() => item.setTrait(CommonStrata.user, "csvString", LatLonValCsv) ); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0]; expect(mapItem instanceof CustomDataSource).toBe(true); if (mapItem instanceof CustomDataSource) { expect(mapItem.entities.values.length).toBe(5); } }); it("removes duplicate rows when requested", async function () { runInAction(() => { item.setTrait(CommonStrata.user, "csvString", LatLonValCsvDuplicate); item.setTrait(CommonStrata.user, "removeDuplicateRows", true); }); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0]; expect(mapItem instanceof CustomDataSource).toBe(true); if (mapItem instanceof CustomDataSource) { expect(mapItem.entities.values.length).toBe(5); const duplicateValue = 7; let occurrences = 0; for (const entity of mapItem.entities.values) { const val = entity.properties?.value.getValue(); if (val === duplicateValue) { occurrences++; } } expect(occurrences).toBe(1); } }); it("has the correct property names", async function () { runInAction(() => item.setTrait(CommonStrata.user, "csvString", LatLonValCsv) ); (await item.loadMapItems()).throwIfError(); const dataSource = item.mapItems[0] as CustomDataSource; const propertyNames = dataSource.entities.values[0].properties?.propertyNames; expect(propertyNames).toEqual(["lat", "lon", "value"]); }); }); describe("when the time column has bad datetimes in it", function () { it("ignores them gracefully", async function () { runInAction(() => item.setTrait(CommonStrata.user, "csvString", BadDatesCsv) ); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0]; expect(mapItem instanceof CustomDataSource).toBe(true); if (mapItem instanceof CustomDataSource) { expect(mapItem.entities.values.length).toBe(3); } }); }); describe("when the table has time-series points with intervals", function () { let dataSource: CustomDataSource; beforeEach(async function () { item.setTrait(CommonStrata.user, "csvString", ParkingSensorDataCsv); (await item.loadMapItems()).throwIfError(); dataSource = item.mapItems[0] as CustomDataSource; expect(dataSource instanceof CustomDataSource).toBe(true); }); it("creates one entity per id", function () { expect(dataSource.entities.values.length).toBe(21); }); it("creates correct intervals", function () { expect(item.activeTableStyle.timeIntervals?.length).toBe(21); expect(item.disableDateTimeSelector).toBeFalsy(); expect( item.activeTableStyle.timeIntervals?.map((t) => [ t?.start.toString(), t?.stop.toString() ]) ).toEqual([ ["2021-06-25T10:39:02Z", "2021-06-26T10:39:01Z"], ["2021-06-25T10:26:45Z", "2021-06-26T10:26:44Z"], ["2021-06-25T10:18:01Z", "2021-06-26T10:18:00Z"], ["2021-06-25T09:53:52Z", "2021-06-26T09:53:51Z"], ["2021-06-25T09:51:32Z", "2021-06-26T09:51:31Z"], ["2021-06-25T09:47:06Z", "2021-06-26T09:47:05Z"], ["2021-06-25T09:19:21Z", "2021-06-26T09:19:20Z"], ["2021-06-25T09:14:36Z", "2021-06-26T09:14:35Z"], ["2021-06-25T09:06:47Z", "2021-06-26T09:06:46Z"], ["2021-06-25T09:01:32Z", "2021-06-26T09:01:31Z"], ["2021-06-25T08:25:09Z", "2021-06-26T08:25:08Z"], ["2021-06-25T07:22:15Z", "2021-06-26T07:22:14Z"], ["2021-06-25T06:10:52Z", "2021-06-26T06:10:51Z"], ["2021-06-25T04:39:45Z", "2021-06-26T04:39:44Z"], ["2021-06-25T03:46:13Z", "2021-06-26T03:46:12Z"], ["2021-06-25T00:29:26Z", "2021-06-26T00:29:25Z"], ["2021-06-25T00:27:23Z", "2021-06-26T00:27:22Z"], ["2021-06-24T14:39:42Z", "2021-06-25T14:39:41Z"], ["2021-06-15T02:50:37Z", "2021-06-16T02:50:36Z"], ["2021-05-12T00:52:56Z", "2021-05-13T00:52:55Z"], ["2021-05-04T03:55:39Z", "2021-05-05T03:55:38Z"] ]); }); it("creates correct intervals if spreadStartTime", function () { runInAction(() => item.setTrait( CommonStrata.user, "defaultStyle", createStratumInstance(TableStyleTraits, { time: createStratumInstance(TableTimeStyleTraits, { spreadStartTime: true }) }) ) ); expect(item.disableDateTimeSelector).toBeFalsy(); expect(item.activeTableStyle.timeIntervals?.length).toBe(21); expect( item.activeTableStyle.timeIntervals?.map((t) => [ t?.start.toString(), t?.stop.toString() ]) ).toEqual([ ["2021-05-04T03:55:39Z", "2021-06-26T10:39:01Z"], ["2021-05-04T03:55:39Z", "2021-06-26T10:26:44Z"], ["2021-05-04T03:55:39Z", "2021-06-26T10:18:00Z"], ["2021-05-04T03:55:39Z", "2021-06-26T09:53:51Z"], ["2021-05-04T03:55:39Z", "2021-06-26T09:51:31Z"], ["2021-05-04T03:55:39Z", "2021-06-26T09:47:05Z"], ["2021-05-04T03:55:39Z", "2021-06-26T09:19:20Z"], ["2021-05-04T03:55:39Z", "2021-06-26T09:14:35Z"], ["2021-05-04T03:55:39Z", "2021-06-26T09:06:46Z"], ["2021-05-04T03:55:39Z", "2021-06-26T09:01:31Z"], ["2021-05-04T03:55:39Z", "2021-06-26T08:25:08Z"], ["2021-05-04T03:55:39Z", "2021-06-26T07:22:14Z"], ["2021-05-04T03:55:39Z", "2021-06-26T06:10:51Z"], ["2021-05-04T03:55:39Z", "2021-06-26T04:39:44Z"], ["2021-05-04T03:55:39Z", "2021-06-26T03:46:12Z"], ["2021-05-04T03:55:39Z", "2021-06-26T00:29:25Z"], ["2021-05-04T03:55:39Z", "2021-06-26T00:27:22Z"], ["2021-05-04T03:55:39Z", "2021-06-25T14:39:41Z"], ["2021-05-04T03:55:39Z", "2021-06-16T02:50:36Z"], ["2021-05-04T03:55:39Z", "2021-05-13T00:52:55Z"], ["2021-05-04T03:55:39Z", "2021-05-05T03:55:38Z"] ]); }); it("creates correct intervals if spreadStartTime and spreadFinishTime", function () { runInAction(() => item.setTrait( CommonStrata.user, "defaultStyle", createStratumInstance(TableStyleTraits, { time: createStratumInstance(TableTimeStyleTraits, { spreadStartTime: true, spreadFinishTime: true }) }) ) ); expect(item.disableDateTimeSelector).toBeTruthy(); expect(item.activeTableStyle.timeIntervals?.length).toBe(21); expect(item.activeTableStyle.moreThanOneTimeInterval).toBe(false); }); it("creates correct intervals if spreadFinishTime", function () { runInAction(() => item.setTrait( CommonStrata.user, "defaultStyle", createStratumInstance(TableStyleTraits, { time: createStratumInstance(TableTimeStyleTraits, { spreadFinishTime: true }) }) ) ); expect(item.activeTableStyle.timeIntervals?.length).toBe(21); expect( item.activeTableStyle.timeIntervals?.map((t) => [ t?.start.toString(), t?.stop.toString() ]) ).toEqual([ ["2021-06-25T10:39:02Z", "2021-06-26T10:39:01Z"], ["2021-06-25T10:26:45Z", "2021-06-26T10:39:01Z"], ["2021-06-25T10:18:01Z", "2021-06-26T10:39:01Z"], ["2021-06-25T09:53:52Z", "2021-06-26T10:39:01Z"], ["2021-06-25T09:51:32Z", "2021-06-26T10:39:01Z"], ["2021-06-25T09:47:06Z", "2021-06-26T10:39:01Z"], ["2021-06-25T09:19:21Z", "2021-06-26T10:39:01Z"], ["2021-06-25T09:14:36Z", "2021-06-26T10:39:01Z"], ["2021-06-25T09:06:47Z", "2021-06-26T10:39:01Z"], ["2021-06-25T09:01:32Z", "2021-06-26T10:39:01Z"], ["2021-06-25T08:25:09Z", "2021-06-26T10:39:01Z"], ["2021-06-25T07:22:15Z", "2021-06-26T10:39:01Z"], ["2021-06-25T06:10:52Z", "2021-06-26T10:39:01Z"], ["2021-06-25T04:39:45Z", "2021-06-26T10:39:01Z"], ["2021-06-25T03:46:13Z", "2021-06-26T10:39:01Z"], ["2021-06-25T00:29:26Z", "2021-06-26T10:39:01Z"], ["2021-06-25T00:27:23Z", "2021-06-26T10:39:01Z"], ["2021-06-24T14:39:42Z", "2021-06-26T10:39:01Z"], ["2021-06-15T02:50:37Z", "2021-06-26T10:39:01Z"], ["2021-05-12T00:52:56Z", "2021-06-26T10:39:01Z"], ["2021-05-04T03:55:39Z", "2021-06-26T10:39:01Z"] ]); }); it("creates disable time dimension by default for this dataset", function () { expect(item.timeDisableDimension).toBeDefined(); }); it("doesn't disable time dimension if `showDisableTimeOption = false`", function () { runInAction(() => item.setTrait(CommonStrata.user, "showDisableTimeOption", false) ); expect(item.timeDisableDimension).toBeUndefined(); }); it("doesn't disable time dimension by default for another dataset", async function () { runInAction(() => { item.setTrait(CommonStrata.user, "csvString", LatLonEnumDateIdCsv); }); (await item.loadMapItems()).throwIfError(); expect(item.timeDisableDimension).toBeUndefined(); }); it("creates disable time dimension for another dataset if `showDisableTimeOption = true`", async function () { runInAction(() => { item.setTrait(CommonStrata.user, "csvString", LatLonEnumDateIdCsv); item.setTrait(CommonStrata.user, "showDisableTimeOption", true); }); (await item.loadMapItems()).throwIfError(); expect(item.timeDisableDimension).toBeDefined(); }); }); describe("when the table has a few styles", function () { it("creates all styleDimensions", async function () { runInAction(() => { item.setTrait(CommonStrata.user, "csvString", LatLonEnumDateIdCsv); }); (await item.loadMapItems()).throwIfError(); expect(item.styleDimensions?.options?.length).toBe(4); expect(item.styleDimensions?.options?.[2].id).toBe("value"); expect(item.styleDimensions?.options?.[2].name).toBe("Value"); }); it("creates all styleDimensions - with disable style", async function () { runInAction(() => { item.setTrait(CommonStrata.user, "csvString", LatLonEnumDateIdCsv); item.setTrait(CommonStrata.user, "showDisableStyleOption", true); }); (await item.loadMapItems()).throwIfError(); expect(item.styleDimensions?.options?.length).toBe(4); expect(item.styleDimensions?.allowUndefined).toBeTruthy(); expect(item.styleDimensions?.undefinedLabel).toBe( "models.tableData.styleDisabledLabel" ); }); it("uses TableColumnTraits for style title", async function () { runInAction(() => { item.setTrait(CommonStrata.user, "csvString", LatLonEnumDateIdCsv); updateModelFromJson(item, CommonStrata.definition, { columns: [{ name: "value", title: "Some Title" }] }); }); (await item.loadMapItems()).throwIfError(); expect(item.styleDimensions?.options?.[2].id).toBe("value"); expect(item.styleDimensions?.options?.[2].name).toBe("Some Title"); }); it("uses TableStyleTraits for style title", async function () { runInAction(() => { item.setTrait(CommonStrata.user, "csvString", LatLonEnumDateIdCsv); updateModelFromJson(item, CommonStrata.definition, { columns: [{ name: "value", title: "Some Title" }], styles: [{ id: "value", title: "Some Style Title" }] }); }); (await item.loadMapItems()).throwIfError(); expect(item.styleDimensions?.options?.[2].id).toBe("value"); expect(item.styleDimensions?.options?.[2].name).toBe("Some Style Title"); }); it("loads regionProviderLists on loadMapItems", async function () { item.setTrait(CommonStrata.user, "csvString", LatLonEnumDateIdCsv); (await item.loadMetadata()).throwIfError(); expect(item.regionProviderLists).toBeUndefined(); (await item.loadMapItems()).throwIfError(); expect(item.regionProviderLists?.[0]?.regionProviders.length).toBe( NUMBER_OF_REGION_MAPPING_TYPES ); }); it("loads regionProviderLists on loadMapItems - with multiple regionMappingDefinitionsUrl", async function () { // We add "additionalRegion.json" - which defines two region types // - "SOME_OTHER_REGION" - which is just another region type // - "SOME_OVERRIDDEN_REGION" - which will override "LGA_NAME_2011" in "build/TerriaJS/data/regionMapping.json" worker.use( http.get("*/additionalRegion.json", () => HttpResponse.json(additionalRegionMapping) ), http.get( "build/TerriaJS/data/regionids/region_map-FID_LGA_2011_AUST_LGA_NAME11.json", () => HttpResponse.json(regionIdsLgaNameStates) ), http.get( "build/TerriaJS/data/regionids/region_map-FID_LGA_2011_AUST_STE_NAME11.json", () => HttpResponse.json(regionIdsLgaName) ) ); terria.updateParameters({ regionMappingDefinitionsUrls: [ "additionalRegion.json", "build/TerriaJS/data/regionMapping.json" ] }); item.setTrait(CommonStrata.user, "csvString", LgaWithDisambigCsv); (await item.loadMetadata()).throwIfError(); expect(item.regionProviderLists).toBeUndefined(); (await item.loadMapItems()).throwIfError(); expect(item.regionProviderLists?.length).toBe(2); expect(item.regionProviderLists?.[0]?.regionProviders.length).toBe(2); expect(item.regionProviderLists?.[1]?.regionProviders.length).toBe( NUMBER_OF_REGION_MAPPING_TYPES ); // Item region provider should match from "additionalRegion.json" (as it comes before "build/TerriaJS/data/regionMapping.json") expect(item.activeTableStyle.regionColumn?.regionType?.description).toBe( "Local Government Areas 2011 by name (ABS) !!!! OVERRIDDEN" ); }); it("loads regionProviderLists on loadMapItems - will use regionMappingDefinitionsUrl instead of regionMappingDefinitionsUrls", async function () { // We add "additionalRegion.json" - which defines two region types // - "SOME_OTHER_REGION" - which is just another region type // - "SOME_OVERRIDDEN_REGION" - which will override "LGA_NAME_2011" in "build/TerriaJS/data/regionMapping.json" worker.use( http.get("*/additionalRegion.json", () => HttpResponse.json(additionalRegionMapping) ), http.get( "build/TerriaJS/data/regionids/region_map-FID_LGA_2011_AUST_LGA_NAME11.json", () => HttpResponse.json(regionIdsLgaNameStates) ), http.get( "build/TerriaJS/data/regionids/region_map-FID_LGA_2011_AUST_STE_NAME11.json", () => HttpResponse.json(regionIdsLgaName) ) ); terria.updateParameters({ regionMappingDefinitionsUrl: "build/TerriaJS/data/regionMapping.json", regionMappingDefinitionsUrls: [ "additionalRegion.json", "build/TerriaJS/data/regionMapping.json" ] }); item.setTrait(CommonStrata.user, "csvString", LgaWithDisambigCsv); (await item.loadMetadata()).throwIfError(); expect(item.regionProviderLists).toBeUndefined(); (await item.loadMapItems()).throwIfError(); expect(item.regionProviderLists?.length).toBe(1); expect(item.regionProviderLists?.[0]?.regionProviders.length).toBe( NUMBER_OF_REGION_MAPPING_TYPES ); // Item region provider should match from "build/TerriaJS/data/regionMapping.json" expect(item.activeTableStyle.regionColumn?.regionType?.description).toBe( "Local Government Areas 2011 by name (ABS)" ); }); }); describe("creates legend", function () { it(" - correct decimal places for values [0,100]", async function () { item.setTrait("definition", "csvString", LegendDecimalPlacesCsv); item.setTrait("definition", "activeStyle", "0dp"); (await item.loadMapItems()).throwIfError(); expect(item.legends[0].items.length).toBe(7); expect(item.legends[0].items.map((i) => i.title)).toEqual([ "65", "54", "44", "33", "22", "12", "1" ]); }); it(" - correct decimal places for values [0,10]", async function () { item.setTrait("definition", "csvString", LegendDecimalPlacesCsv); item.setTrait("definition", "activeStyle", "1dp"); (await item.loadMapItems()).throwIfError(); expect(item.legends[0].items.length).toBe(7); expect(item.legends[0].items.map((i) => i.title)).toEqual([ "10.0", "8.3", "6.7", "5.0", "3.3", "1.7", "0.0" ]); }); it(" - correct decimal places for values [0,1]", async function () { item.setTrait("definition", "csvString", LegendDecimalPlacesCsv); item.setTrait("definition", "activeStyle", "2dp"); (await item.loadMapItems()).throwIfError(); expect(item.legends[0].items.length).toBe(7); expect(item.legends[0].items.map((i) => i.title)).toEqual([ "0.70", "0.58", "0.47", "0.35", "0.23", "0.12", "0.00" ]); }); it(" - correct decimal places for values [0,0.1]", async function () { item.setTrait("definition", "csvString", LegendDecimalPlacesCsv); item.setTrait("definition", "activeStyle", "3dp"); (await item.loadMapItems()).throwIfError(); expect(item.legends[0].items.length).toBe(7); expect(item.legends[0].items.map((i) => i.title)).toEqual([ "0.080", "0.068", "0.057", "0.045", "0.033", "0.022", "0.010" ]); }); it(" - uses color column title by default", async function () { item.setTrait("definition", "csvString", LegendDecimalPlacesCsv); item.setTrait("definition", "activeStyle", "0dp"); updateModelFromJson(item, CommonStrata.user, { styles: [{ name: "0dp", title: "Some title" }] }); (await item.loadMapItems()).throwIfError(); expect(item.legends[0].title).toBe("0dp"); }); }); describe("region mapping - LGA with disambig", function () { beforeEach(async function () { item.setTrait(CommonStrata.user, "csvString", LgaWithDisambigCsv); (await item.loadMapItems()).throwIfError(); await item.regionProviderLists?.[0] ?.getRegionProvider("LGA_NAME_2011") ?.loadRegionIDs(); await item.regionProviderLists?.[0] ?.getRegionProvider("STE_NAME_2016") ?.loadRegionIDs(); }); it("creates imagery parts", function () { expect(ImageryParts.is(item.mapItems[0])).toBeTruthy(); }); it("with state", function () { updateModelFromJson(item, CommonStrata.user, { columns: [ { name: "State", regionType: "STE_NAME_2016" } ], defaultStyle: { regionColumn: "State" } }); expect(item.activeTableStyle.regionColumn?.name).toBe("State"); expect(item.activeTableStyle.regionColumn?.regionType?.regionType).toBe( "STE_NAME_2016" ); expect( item.activeTableStyle.regionColumn?.valuesAsRegions.numberOfValidRegions ).toBe(8); expect( item.activeTableStyle.regionColumn?.valuesAsRegions.uniqueRegionIds .length ).toBe(3); }); it("with lga_name", function () { updateModelFromJson(item, CommonStrata.user, { columns: [ { name: "LGA_NAME", regionType: "LGA_NAME_2011" } ], defaultStyle: { regionColumn: "LGA_NAME" } }); expect(item.activeTableStyle.regionColumn?.name).toBe("LGA_NAME"); expect(item.activeTableStyle.regionColumn?.regionType?.regionType).toBe( "LGA_NAME_2011" ); expect( item.activeTableStyle.regionColumn?.valuesAsRegions.numberOfValidRegions ).toBe(8); expect( item.activeTableStyle.regionColumn?.valuesAsRegions.uniqueRegionIds .length ).toBe(8); }); it("matches column name with whitespace", async function () { item.setTrait( CommonStrata.user, "csvString", `lga code-_-2015,number 35740,1 36720,2 ` ); (await item.loadMapItems()).throwIfError(); expect(item.activeTableStyle.regionColumn?.name).toBe("lga code-_-2015"); expect(item.activeTableStyle.regionColumn?.regionType?.regionType).toBe( "LGA_2015" ); }); it("shows region shortReportSection", function () { const regionCol = item.activeTableStyle.regionColumn; const regionType = regionCol?.regionType; expect(regionType).toBeDefined(); expect(item.shortReportSections[0].name).toBe( `**Regions:** ${regionType?.description}` ); }); it("doesn't show region shortReportSection if region is disabled", function () { updateModelFromJson(item, CommonStrata.user, { defaultStyle: { regionColumn: "Something else" } }); expect(item.shortReportSections.length).toBe(0); }); }); describe("applies TableStyles to lat/lon features", function () { it("supports image marker style - data URI", async function () { item.setTrait(CommonStrata.user, "csvString", LatLonValCsv); const image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAZNJREFUWIXtlrFLQlEUxr/QPGYhTbYEhhgWErjU0twQ9AdEGNnU0CiBL60pMBqC2gSHhgoamhoFt8ZaIugtQhFFY1Hmp0EN+ehZDd3e84ngB493733vnPPjXj7OdaPFcncA2h3AIyLrJBMiskcy01QAEdkgmTavkTTeaQDpbyFdtgKQXFH5/y9SPQKPefII7PuB2Xqe0xGRgE4ONxOgQX4gbppOHpGlmGIOW10wCoRUY2wFKP0jxhJAHMAqgCCAawBRpwEO6o8VWQKYjqK8lYAEA3Bd3UGf0BBxFOBYg6+n+3M8HkJkaQqVXAFexwCM4oZ2F+HNFdRytHczeq017sJyHi8Aeh0DmMniaSeB96EBeC5ucJ4vYlI1hyWA4iX8Y1/tSbm4ZQCJohxegHgDcD3fQtczDtswtgafMe4PIxLZRElPqfUDW13QN9jiZlR5UI+xBPBWA9wmG96fNN+GVZhuRWfzP74rFVcGEJFtkinVIrYBkNQAaKYlj4hkSc6JyCHJZFMBflG1XjRpXM+dBrCsDsAHoPtrwlSQt8wAAAAASUVORK5CYII="; item.setTrait(CommonStrata.user, "styles", [ createStratumInstance(TableStyleTraits, { id: "test-style", point: createStratumInstance(TablePointStyleTraits, { null: createStratumInstance(PointSymbolTraits, { marker: image, height: 20 }) }) }) ]); item.setTrait(CommonStrata.user, "activeStyle", "test-style"); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0] as CustomDataSource; mapItem.entities.values.forEach((feature) => { expect( feature.billboard?.image?.getValue( item.terria.timelineClock.currentTime ) ).toBe(image); expect( feature.billboard?.height?.getValue( item.terria.timelineClock.currentTime ) ).toBe(20); }); }); it("supports image marker style - URL", async function () { item.setTrait(CommonStrata.user, "csvString", LatLonValCsv); const image = "http://localhost:3001/build/TerriaJS/images/map-pin.svg"; item.setTrait(CommonStrata.user, "styles", [ createStratumInstance(TableStyleTraits, { id: "test-style", point: createStratumInstance(TablePointStyleTraits, { null: createStratumInstance(PointSymbolTraits, { marker: image, height: 20 }) }) }) ]); item.setTrait(CommonStrata.user, "activeStyle", "test-style"); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0] as CustomDataSource; mapItem.entities.values.forEach((feature) => { expect( feature.billboard?.image?.getValue( item.terria.timelineClock.currentTime ) ).toBe(image); expect( feature.billboard?.height?.getValue( item.terria.timelineClock.currentTime ) ).toBe(20); }); }); it("bin outline style with points", async function () { item.setTrait(CommonStrata.user, "csvString", LatLonValCsv); item.setTrait(CommonStrata.user, "styles", [ createStratumInstance(TableStyleTraits, { id: "test-style", color: createStratumInstance(TableColorStyleTraits, { colorColumn: "value", colorPalette: "Greens", numberOfBins: 7 }), point: createStratumInstance(TablePointStyleTraits, { column: "value", bin: [ createStratumInstance(BinPointSymbolTraits, { maxValue: 1, marker: "point", height: 20 }), createStratumInstance(BinPointSymbolTraits, { maxValue: 3, marker: "point", height: 10 }), createStratumInstance(BinPointSymbolTraits, { maxValue: 5, marker: "point", height: 30 }) ] }), outline: createStratumInstance(TableOutlineStyleTraits, { column: "value", bin: [ createStratumInstance(BinOutlineSymbolTraits, { maxValue: 1, color: "rgb(0,0,0)", width: 1 }), createStratumInstance(BinOutlineSymbolTraits, { maxValue: 3, color: "rgb(255,0,0)", width: 2 }), createStratumInstance(BinOutlineSymbolTraits, { maxValue: 5, color: "rgb(0,255,0)", width: 3 }) ] }) }) ]); item.setTrait(CommonStrata.user, "activeStyle", "test-style"); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0] as CustomDataSource; const styles = [ { fillColor: "rgb(35,139,69)", outlineColor: "rgb(0,255,0)", outlineWidth: 3, pixelSize: 30 }, { fillColor: "rgb(116,196,118)", outlineColor: "rgb(255,0,0)", outlineWidth: 2, pixelSize: 10 }, { fillColor: "rgb(186,228,179)", outlineColor: "rgb(0,0,0)", outlineWidth: 1, pixelSize: 20 }, { fillColor: "rgb(237,248,233)", outlineColor: "rgb(0,0,0)", outlineWidth: 1, pixelSize: 20 }, { fillColor: "rgb(116,196,118)", outlineColor: "rgb(255,0,0)", outlineWidth: 2, pixelSize: 10 } ]; styles.forEach((style, index) => { const feature = mapItem.entities.values[index]; expect( feature.point?.color ?.getValue(item.terria.timelineClock.currentTime) ?.toCssColorString() ).toBe(style.fillColor); expect( feature.point?.outlineColor ?.getValue(item.terria.timelineClock.currentTime) ?.toCssColorString() ).toBe(style.outlineColor); expect( feature.point?.outlineWidth?.getValue( item.terria.timelineClock.currentTime ) ).toBe(style.outlineWidth); expect( feature.point?.pixelSize?.getValue( item.terria.timelineClock.currentTime ) ).toBe(style.pixelSize); }); }); it("bin color and outline style with markers", async function () { item.setTrait(CommonStrata.user, "csvString", LatLonValCsv); item.setTrait(CommonStrata.user, "styles", [ createStratumInstance(TableStyleTraits, { id: "test-style", color: createStratumInstance(TableColorStyleTraits, { nullColor: "rgb(0,255,255)" }), point: createStratumInstance(TablePointStyleTraits, { column: "value", bin: [ createStratumInstance(BinPointSymbolTraits, { maxValue: 1, marker: "circle", height: 20, width: 10 }), createStratumInstance(BinPointSymbolTraits, { maxValue: 3, marker: "cross", height: 10, width: 5 }), createStratumInstance(BinPointSymbolTraits, { maxValue: 5, marker: "hospital", height: 30, width: 15, rotation: 45 }) ] }), outline: createStratumInstance(TableOutlineStyleTraits, { null: createStratumInstance(BinOutlineSymbolTraits, { maxValue: 1, color: "rgb(0,0,255)", width: 1 }) }) }) ]); item.setTrait(CommonStrata.user, "activeStyle", "test-style"); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0] as CustomDataSource; const styles = [ { fillColor: "rgb(0,255,255)", outlineColor: "rgb(0,0,255)", outlineWidth: 1, marker: "hospital", height: 30, width: 15, // Convert to counter-clockwise radians rotation: ((360 - 45) / 360) * (2 * Math.PI) }, { fillColor: "rgb(0,255,255)", outlineColor: "rgb(0,0,255)", outlineWidth: 1, marker: "cross", height: 10, width: 5, rotation: 2 * Math.PI }, { fillColor: "rgb(0,255,255)", outlineColor: "rgb(0,0,255)", outlineWidth: 1, marker: "circle", height: 20, width: 10, rotation: 2 * Math.PI }, { fillColor: "rgb(0,255,255)", outlineColor: "rgb(0,0,255)", outlineWidth: 1, marker: "circle", height: 20, width: 10, rotation: 2 * Math.PI }, { fillColor: "rgb(0,255,255)", outlineColor: "rgb(0,0,255)", outlineWidth: 1, marker: "cross", height: 10, width: 5, rotation: 2 * Math.PI } ]; styles.forEach((style, index) => { const feature = mapItem.entities.values[index]; expect( feature.billboard?.rotation?.getValue( item.terria.timelineClock.currentTime ) ).toBeCloseTo(style.rotation); expect( feature.billboard?.image?.getValue( item.terria.timelineClock.currentTime ) ).toBe( getMakiIcon( style.marker, style.fillColor, style.outlineWidth, style.outlineColor, style.height, style.width ) ); }); // Test merging legends expect( item.legends[0].items.map((item) => ({ title: item.title, outlineColor: item.outlineColor, outlineWidth: item.outlineWidth, imageHeight: item.imageHeight, imageWidth: item.imageWidth, color: item.color, marker: item.marker, rotation: item.rotation })) ).toEqual([ { title: "3 to 5", color: "rgb(0,255,255)", outlineColor: "rgb(0,0,255)", outlineWidth: 1, marker: "hospital", rotation: 45, imageHeight: 24, imageWidth: 24 }, { title: "1 to 3", color: "rgb(0,255,255)", outlineColor: "rgb(0,0,255)", outlineWidth: 1, marker: "cross", imageHeight: 24, imageWidth: 24, rotation: 0 }, { title: "-1 to 1", color: "rgb(0,255,255)", outlineColor: "rgb(0,0,255)", outlineWidth: 1, marker: "circle", imageHeight: 24, imageWidth: 24, rotation: 0 } ]); }); it("enum outline style with points", async function () { item.setTrait(CommonStrata.user, "csvString", LatLonEnumCsv); item.setTrait(CommonStrata.user, "styles", [ createStratumInstance(TableStyleTraits, { id: "test-style", color: createStratumInstance(TableColorStyleTraits, { nullColor: "rgb(255,0,255)" }), point: createStratumInstance(TablePointStyleTraits, { column: "enum", enum: [ createStratumInstance(EnumPointSymbolTraits, { value: "hello", height: 20 }), createStratumInstance(EnumPointSymbolTraits, { value: "boots", height: 10 }), createStratumInstance(EnumPointSymbolTraits, { value: "frogs", height: 30 }) ] }), outline: createStratumInstance(TableOutlineStyleTraits, { column: "enum", enum: [ createStratumInstance(EnumOutlineSymbolTraits, { value: "hello", color: "rgb(0,0,0)", width: 1 }), createStratumInstance(EnumOutlineSymbolTraits, { value: "boots", color: "rgb(255,0,0)", width: 2 }), createStratumInstance(EnumOutlineSymbolTraits, { value: "frogs", color: "rgb(0,255,0)", width: 3 }) ] }) }) ]); item.setTrait(CommonStrata.user, "activeStyle", "test-style"); (await item.loadMapItems()).throwIfError(); const mapItem = item.mapItems[0] as CustomDataSource; const styles = [ { fillColor: "rgb(255,0,255)", outlineColor: "rgb(0,0,0)", outlineWidth: 1, pixelSize: 20 }, { fillColor: "rgb(255,0,255)", outlineColor: "rgb(255,0,0)", outlineWidth: 2, pixelSize: 10 }, { fillColor: "rgb(255,0,255)", outlineColor: "rgb(0,255,0)", outlineWidth: 3, pixelSize: 30 }, { fillColor: "rgb(255,0,255)", outlineColor: "rgb(255,0,0)", outlineWidth: 2, pixelSize: 10 }, { fillColor: "rgb(255,0,255)", outlineColor: "rgb(0,0,0)", outlineWidth: 1, pixelSize: 20 } ]; styles.forEach((style, index) => { const feature = mapItem.entities.values[index]; expect( feature.point?.color ?.getValue(item.terria.timelineClock.currentTime) ?.toCssColorString() ).toBe(style.fillColor); expect( feature.point?.outlineColor ?.getValue(item.terria.timelineClock.currentTime) ?.toCssColorString() ).toBe(style.outlineColor); expect( feature.point?.outlineWidth?.getValue( item.terria.timelineClock.currentTime ) ).toBe(style.outlineWidth); expect( feature.point?.pixelSize?.getValue( item.terria.timelineClock.currentTime ) ).toBe(style.pixelSize); // Test merging legends expect( item.legends[0].items.map((item) => ({ title: item.title, outlineColor: item.outlineColor, outlineWidth: item.outlineWidth, imageHeight: item.imageHeight, imageWidth: item.imageWidth })) ).toEqual([ { title: "hello", outlineColor: "rgb(0,0,0)", outlineWidth: 1, imageHeight: 24, imageWidth: 24 }, { title: "boots", outlineColor: "rgb(255,0,0)", outlineWidth: 2, imageHeight: 24, imageWidth: 24 }, { title: "frogs", outlineColor: "rgb(0,255,0)", outlineWidth: 3, imageHeight: 24, imageWidth: 24 } ]); }); }); it("enum label style with points", async function () { item.setTrait(CommonStrata.user, "csvString", LatLonEnumCsv); item.setTrait(CommonStrata.user, "styles", [ createStratumInstance(TableStyleTraits, { id: "test-style", color: createStratumInstance(TableColorStyleTraits, { nullColor: "rgb(255,0,255)" }), label: createStratumInstance(TableLabelStyleTraits, { column: "enum", enabled: true, enum: [ createStratumInstance(EnumLabelSymbolTraits, { value: "hello", labelColumn: "enum", font: "10px sans-serif", style: "FILL", scale: 1.5, fillColor: "#ff00ff", pixelOffset: [0, 0], horizontalOrigin: "LEFT", verticalOrigin: "TOP" }), createStratumInstance(EnumLabelSymbolTraits, { value: "boots", labelColumn: "enum", font: "20px Arial", style: "FILL_AND_OUTLINE", scale: 2, fillColor: "#0000ff", outlineColor: "#00ff00", outlineWidth: 1, pixelOffset: [1, 1], horizontalOrigin: "CENTER", verticalOrigin: "CENTER" }), createStratumInstance(EnumLabelSymbolTraits, { value: "frogs", labelColumn: "lon", font: "30px serif", style: "OUTLINE", scale: 3, outlineColor: "#ff0000", outlineWidth: 2, pixelOffset: [2, 2], horizontalOrigin: "RIGHT", verticalOrigin: "BOTTOM" }) ] }) }) ]); item.setTrait(CommonStrata.user, "activeStyle", "test-style"); (await item.loadMapItems()).throwIfError();