UNPKG

terriajs

Version:

Geospatial data visualization platform.

681 lines (583 loc) 23 kB
import ContinuousColorMap from "../../lib/Map/ColorMap/ContinuousColorMap"; import DiscreteColorMap from "../../lib/Map/ColorMap/DiscreteColorMap"; import EnumColorMap from "../../lib/Map/ColorMap/EnumColorMap"; 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 Terria from "../../lib/Models/Terria"; import LegendTraits, { LegendItemTraits } from "../../lib/Traits/TraitsClasses/LegendTraits"; import TableColorStyleTraits from "../../lib/Traits/TraitsClasses/Table/ColorStyleTraits"; import TableColumnTraits, { ColumnTransformationTraits } from "../../lib/Traits/TraitsClasses/Table/ColumnTraits"; import TableStyleTraits from "../../lib/Traits/TraitsClasses/Table/StyleTraits"; import { http, HttpResponse } from "msw"; import { worker } from "../mocks/browser"; import regionMapping from "../../wwwroot/data/regionMapping.json"; import SedCods from "../../wwwroot/data/regionids/region_map-SED_CODE18_SED_2018.json"; import Sa4Codes from "../../wwwroot/data/regionids/region_map-SA4_2016_AUST_SA4_CODE16.json"; import Sa4Names from "../../wwwroot/data/regionids/region_map-SA4_2016_AUST_SA4_NAME16.json"; import Sa4Names2021 from "../../wwwroot/data/regionids/region_map-SA4_NAME_2021_SA4_2021.json"; import LatLonCsv from "../../wwwroot/test/csv/lat_lon_enum_date_id.csv"; import SedCsv from "../../wwwroot/test/csv/SED_2018_SED_CODE18.csv"; import YouthUnEmployCsv from "../../wwwroot/test/csv/youth-unemployment-rate-2018.csv"; describe("TableStyle", function () { let terria: Terria; beforeEach(function () { terria = new Terria({ baseUrl: "./" }); terria.configParameters.regionMappingDefinitionsUrl = "build/TerriaJS/data/regionMapping.json"; worker.use( http.get("*/build/TerriaJS/data/regionMapping.json", () => HttpResponse.json(regionMapping) ), http.get( "https://tiles.terria.io/region-mapping/regionids/region_map-SED_CODE18_SED_2018.json", () => HttpResponse.json(SedCods) ), http.get( "https://tiles.terria.io/region-mapping/regionids/region_map-SA4_2016_AUST_SA4_CODE16.json", () => HttpResponse.json(Sa4Codes) ), http.get( "https://tiles.terria.io/region-mapping/regionids/region_map-SA4_2016_AUST_SA4_NAME16.json", () => HttpResponse.json(Sa4Names) ), http.get( "https://tiles.terria.io/region-mapping/regionids/region_map-SA4_NAME_2021_SA4_2021.json", () => HttpResponse.json(Sa4Names2021) ), http.all("*", () => HttpResponse.error()) ); }); describe(" - Scalar", function () { let csvItem: CsvCatalogItem; beforeEach(function () { csvItem = new CsvCatalogItem("SmallCsv", terria, undefined); }); it(" - uses DiscreteColorMap if set numberOfBins", async function () { csvItem.setTrait("definition", "csvString", SedCsv); csvItem.setTrait("definition", "styles", [ createStratumInstance(TableStyleTraits, { id: "Value", color: createStratumInstance(TableColorStyleTraits, { numberOfBins: 7 }) }) ]); await csvItem.loadMapItems(); const activeStyle = csvItem.activeTableStyle; const colorColumn = activeStyle.colorColumn; expect(colorColumn).toBeDefined(); expect(colorColumn!.type).toBe(4); expect(colorColumn!.values.length).toBe(450); expect(activeStyle.tableColorMap.binColors.length).toEqual(7); expect(activeStyle.tableColorMap.binMaximums.length).toEqual(7); expect(activeStyle.colorMap instanceof DiscreteColorMap).toBeTruthy(); expect( (activeStyle.colorMap as DiscreteColorMap).colors.map((c) => c.toCssHexString() ) ).toEqual([ "#fee5d9", "#fcbba1", "#fc9272", "#fb6a4a", "#ef3b2c", "#cb181d", "#99000d" ]); }); it(" - uses DiscreteColorMap if set binMaximums", async function () { csvItem.setTrait("definition", "csvString", YouthUnEmployCsv); csvItem.setTrait("definition", "styles", [ createStratumInstance(TableStyleTraits, { id: "youth unemployment (%)", color: createStratumInstance(TableColorStyleTraits, { binMaximums: [8, 10, 15, 20, 30, 50], colorPalette: "PiYG" }) }) ]); await csvItem.loadMapItems(); const activeStyle = csvItem.activeTableStyle; const colorColumn = activeStyle.colorColumn; expect(colorColumn).toBeDefined(); expect(colorColumn!.type).toBe(4); expect(colorColumn!.values.length).toBe(86); expect(activeStyle.tableColorMap.binColors.length).toEqual(6); expect(activeStyle.tableColorMap.binMaximums.length).toEqual(6); expect(activeStyle.colorMap instanceof DiscreteColorMap).toBeTruthy(); expect( (activeStyle.colorMap as DiscreteColorMap).colors.map((c) => c.toCssHexString() ) ).toEqual([ "#c51b7d", "#e9a3c9", "#fde0ef", "#e6f5d0", "#a1d76a", "#4d9221" ]); const colMap = activeStyle.colorMap as DiscreteColorMap; expect(colMap.mapValueToColor(0).toCssHexString()).toBe( "#c51b7d", "0 - which should be first bin (-Infinity, 8]" ); expect(colMap.mapValueToColor(7.9999).toCssHexString()).toBe( "#c51b7d", "7.9999 - which should be first bin (-Infinity, 8]" ); expect(colMap.mapValueToColor(8).toCssHexString()).toBe( "#c51b7d", "8 - which should be first bin (-Infinity, 8]" ); expect(colMap.mapValueToColor(8.0001).toCssHexString()).toBe( "#e9a3c9", "8.0001 - which should be second bin (8,10]" ); expect(colMap.mapValueToColor(9.9999).toCssHexString()).toBe( "#e9a3c9", "9.9999 - which should be second bin (8,10]" ); expect(colMap.mapValueToColor(10).toCssHexString()).toBe( "#e9a3c9", "10 - which should be second bin (8,10]" ); expect(colMap.mapValueToColor(10.0001).toCssHexString()).toBe( "#fde0ef", "10.0001 - which should be third bin (10,15]" ); expect(colMap.mapValueToColor(14.9999).toCssHexString()).toBe( "#fde0ef", "14.9999 - which should be third bin (10,15]" ); expect(colMap.mapValueToColor(15).toCssHexString()).toBe( "#fde0ef", "15 - which should be third bin (10,15]" ); expect(colMap.mapValueToColor(15.0001).toCssHexString()).toBe( "#e6f5d0", "15.0001 - which should be fourth bin (15,20]" ); expect(colMap.mapValueToColor(19.9999).toCssHexString()).toBe( "#e6f5d0", "19.9999 - which should be fourth bin (15,20]" ); expect(colMap.mapValueToColor(20).toCssHexString()).toBe( "#e6f5d0", "20 - which should be fourth bin (15,20]" ); expect(colMap.mapValueToColor(20.0001).toCssHexString()).toBe( "#a1d76a", "20.0001 - which should be fifth bin (20,30]" ); expect(colMap.mapValueToColor(29.9999).toCssHexString()).toBe( "#a1d76a", "29.9999 - which should be fifth bin (20,30]" ); expect(colMap.mapValueToColor(30).toCssHexString()).toBe( "#a1d76a", "30 - which should be fifth bin (20,30]" ); expect(colMap.mapValueToColor(30.0001).toCssHexString()).toBe( "#4d9221", "30.0001 - which should be sixth bin (30,Infinity)" ); expect(colMap.mapValueToColor(60).toCssHexString()).toBe( "#4d9221", "60 - which should be last bin (30,Infinity)" ); // Uncomment when outlierColor support is added to DiscreteColorMap // runInAction(() => // activeStyle.colorTraits.setTrait( // CommonStrata.user, // "outlierColor", // "#ff0000" // ) // ); // // expect(colMap.mapValueToColor(60).toCssHexString()).toBe( // "#ff0000", // "60 - which should be last bin (as outlierColor is undefined)" // ); }); it(" - uses ContinuousColorMap by default", async function () { csvItem.setTrait("definition", "csvString", SedCsv); await csvItem.loadMapItems(); const activeStyle = csvItem.activeTableStyle; const colorColumn = activeStyle.colorColumn; expect(colorColumn).toBeDefined(); expect(colorColumn!.type).toBe(4); expect(colorColumn!.values.length).toBe(450); expect(activeStyle.colorMap instanceof ContinuousColorMap).toBeTruthy(); expect((activeStyle.colorMap as ContinuousColorMap).minValue).toBe(0); expect(activeStyle.tableColorMap.isDiverging).toBeFalsy(); expect((activeStyle.colorMap as ContinuousColorMap).maxValue).toBe(100); expect( (activeStyle.colorMap as ContinuousColorMap) .mapValueToColor(0) .toCssColorString() ).toBe("rgb(255,245,240)"); expect( (activeStyle.colorMap as ContinuousColorMap) .mapValueToColor(50) .toCssColorString() ).toBe("rgb(249,105,76)"); expect( (activeStyle.colorMap as ContinuousColorMap) .mapValueToColor(100) .toCssColorString() ).toBe("rgb(103,0,13)"); }); it(" - uses ContinuousColorMap with diverging color scale if appropriate", async function () { csvItem.setTrait("definition", "csvString", SedCsv); // Add value transformation to turn column values to be [-50,50] csvItem.setTrait("definition", "columns", [ createStratumInstance(TableColumnTraits, { name: "Value", transformation: createStratumInstance(ColumnTransformationTraits, { expression: "x-50" }) }) ]); await csvItem.loadMapItems(); const activeStyle = csvItem.activeTableStyle; const colorColumn = activeStyle.colorColumn; expect(colorColumn).toBeDefined(); expect(colorColumn!.type).toBe(4); expect(colorColumn!.values.length).toBe(450); expect(activeStyle.colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(activeStyle.tableColorMap.isDiverging).toBeTruthy(); expect((activeStyle.colorMap as ContinuousColorMap).minValue).toBe(-50); expect((activeStyle.colorMap as ContinuousColorMap).maxValue).toBe(50); expect( (activeStyle.colorMap as ContinuousColorMap) .mapValueToColor(0) .toCssColorString() ).toBe("rgb(243,238,234)"); expect( (activeStyle.colorMap as ContinuousColorMap) .mapValueToColor(-50) .toCssColorString() ).toBe("rgb(45,0,75)"); expect( (activeStyle.colorMap as ContinuousColorMap) .mapValueToColor(50) .toCssColorString() ).toBe("rgb(127,59,8)"); }); it(" - uses ContinuousColorMap with diverging color map only for diverging color palettes", async function () { csvItem.setTrait("definition", "csvString", SedCsv); // Add value transformation to turn column values to be [-50,50] csvItem.setTrait("definition", "columns", [ createStratumInstance(TableColumnTraits, { name: "Value", transformation: createStratumInstance(ColumnTransformationTraits, { expression: "x-50" }) }) ]); await csvItem.loadMapItems(); const activeStyle = csvItem.activeTableStyle; const colorColumn = activeStyle.colorColumn; expect(colorColumn).toBeDefined(); expect(colorColumn!.type).toBe(4); expect(colorColumn!.values.length).toBe(450); expect(activeStyle.colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(activeStyle.tableColorMap.isDiverging).toBeTruthy(); // Set colorpalette to Reds - which is not diverging csvItem.setTrait( "definition", "defaultStyle", createStratumInstance(TableStyleTraits, { color: createStratumInstance(TableColorStyleTraits, { colorPalette: "Reds" }) }) ); expect(activeStyle.colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(activeStyle.tableColorMap.isDiverging).toBeFalsy(); // Set colorpalette to RdYlBu - which is diverging csvItem.setTrait( "definition", "defaultStyle", createStratumInstance(TableStyleTraits, { color: createStratumInstance(TableColorStyleTraits, { colorPalette: "RdYlBu" }) }) ); expect(activeStyle.colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(activeStyle.tableColorMap.isDiverging).toBeTruthy(); }); it(" - handles ContinuousColorMap with single value ", async function () { csvItem.setTrait( "definition", "csvString", `SED_CODE18,Value\na,23\nb,23\nc,23\nd,23` ); await csvItem.loadMapItems(); const activeStyle = csvItem.activeTableStyle; const colorColumn = activeStyle.colorColumn; expect(colorColumn).toBeDefined(); expect(colorColumn!.type).toBe(4); expect(colorColumn!.values.length).toBe(4); expect(activeStyle.colorMap instanceof EnumColorMap).toBeTruthy(); }); describe(" - applies zScoreFilter, outlierColor and minimumValue/maximumValue correctly", function () { beforeEach(async function () { updateModelFromJson(csvItem, CommonStrata.definition, { csvString: SedCsv, activeStyle: "Value", defaultStyle: { color: { zScoreFilter: 2, rangeFilter: 0.1, zScoreFilterEnabled: true } } }); await csvItem.loadMapItems(); await csvItem.activeTableStyle.regionColumn?.regionType?.loadRegionIDs(); }); it(" - should expect no filter applied", function () { expect( csvItem.activeTableStyle.colorColumn?.valuesAsNumbers.minimum ).toBe(0); expect( csvItem.activeTableStyle.colorColumn?.valuesAsNumbers.maximum ).toBe(100); expect( csvItem.activeTableStyle.tableColorMap.zScoreFilterValues ).toBeUndefined(); const colorMap = csvItem.activeTableStyle .colorMap as ContinuousColorMap; expect(colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(colorMap.minValue).toBe(0); expect(colorMap.maxValue).toBe(100); // Check legend for no outlier item expect(csvItem.legends.length).toBe(1); expect(csvItem.legends[0].items.length).toBe(7); }); it(" - Change zScoreFilter and rangeFilter - should also expect not to be applied", function () { updateModelFromJson(csvItem, CommonStrata.definition, { defaultStyle: { color: { zScoreFilter: 1, rangeFilter: 0.25, zScoreFilterEnabled: true } } }); expect( csvItem.activeTableStyle.tableColorMap.zScoreFilterValues ).toBeUndefined(); const colorMap = csvItem.activeTableStyle .colorMap as ContinuousColorMap; expect(colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(colorMap.minValue).toBe(0); expect(colorMap.maxValue).toBe(100); // Check legend for no outlier item expect(csvItem.legends.length).toBe(1); expect(csvItem.legends[0].items.length).toBe(7); }); it(" - Change zScoreFilter and rangeFilter again - should be applied this time", function () { updateModelFromJson(csvItem, CommonStrata.definition, { defaultStyle: { color: { zScoreFilter: 1, rangeFilter: 0.1, zScoreFilterEnabled: true } } }); expect( csvItem.activeTableStyle.tableColorMap.zScoreFilterValues ).toEqual({ min: 22, max: 80 }); const colorMap = csvItem.activeTableStyle .colorMap as ContinuousColorMap; expect(colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(colorMap.minValue).toBe(22); expect(colorMap.maxValue).toBe(80); expect(colorMap.mapValueToColor(0)).toEqual( csvItem.activeTableStyle.tableColorMap.outlierColor! ); // Check legend for outlier item expect(csvItem.legends.length).toBe(1); expect(csvItem.legends[0].items.length).toBe(8); expect(csvItem.legends[0].items[7].title).toBe( "models.tableData.legendZFilterLabel" ); expect(csvItem.legends[0].items[7].addSpacingAbove).toBeTruthy(); expect(csvItem.legends[0].items[7].color).toBe( csvItem.activeTableStyle.tableColorMap.outlierColor?.toCssColorString() ); }); it(" - Set colorTraits.minimumValue to disable zScoreFilter", function () { updateModelFromJson(csvItem, CommonStrata.definition, { defaultStyle: { color: { zScoreFilter: 1, rangeFilter: 0.1, zScoreFilterEnabled: true, minimumValue: 22 } } }); expect( csvItem.activeTableStyle.tableColorMap.outlierColor ).toBeUndefined(); expect( csvItem.activeTableStyle.tableColorMap.zScoreFilterValues ).toBeUndefined(); const colorMap = csvItem.activeTableStyle .colorMap as ContinuousColorMap; expect(colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(colorMap.minValue).toBe(22); expect(colorMap.maxValue).toBe(100); expect(colorMap.mapValueToColor(0)).toEqual( colorMap.mapValueToColor(22) ); }); it(" - Set colorTraits.maximumValue to disable zScoreFilter", function () { updateModelFromJson(csvItem, CommonStrata.definition, { defaultStyle: { color: { zScoreFilter: 1, rangeFilter: 0.1, zScoreFilterEnabled: true, maximumValue: 80 } } }); expect( csvItem.activeTableStyle.tableColorMap.outlierColor ).toBeUndefined(); expect( csvItem.activeTableStyle.tableColorMap.zScoreFilterValues ).toBeUndefined(); const colorMap = csvItem.activeTableStyle .colorMap as ContinuousColorMap; expect(colorMap instanceof ContinuousColorMap).toBeTruthy(); expect(colorMap.minValue).toBe(0); expect(colorMap.maxValue).toBe(80); expect(colorMap.mapValueToColor(100)).toEqual( colorMap.mapValueToColor(80) ); }); it(" - Now if we set min/max outside range, then colorMap.outlierColor should be undefined", function () { updateModelFromJson(csvItem, CommonStrata.definition, { defaultStyle: { color: { zScoreFilter: 1, rangeFilter: 0.1, zScoreFilterEnabled: true, maximumValue: 101, minimumValue: -1, outlierColor: "#00ff00" } } }); const colorMap = csvItem.activeTableStyle .colorMap as ContinuousColorMap; expect(colorMap.minValue).toBe(-1); expect(colorMap.maxValue).toBe(101); expect(colorMap.outlierColor).toBeUndefined(); }); }); it(" - applied colorTraits on top of TableLegendStratum", async function () { csvItem.setTrait("definition", "csvString", SedCsv); csvItem.setTrait("definition", "styles", [ createStratumInstance(TableStyleTraits, { id: "Value", color: createStratumInstance(TableColorStyleTraits, { numberOfBins: 7, legend: createStratumInstance(LegendTraits, { title: "Some other title", items: [ createStratumInstance(LegendItemTraits, { color: "what" }) ] }) }) }) ]); await csvItem.loadMapItems(); expect(csvItem.legends[0].title).toBe("Some other title"); expect(csvItem.legends[0].items.length).toBe(1); expect(csvItem.legends[0].items[0].color).toBe("what"); }); }); describe(" - Enum", function () { let csvItem: CsvCatalogItem; beforeEach(function () { csvItem = new CsvCatalogItem("SmallCsv", terria, undefined); }); it(" - uses EnumColorMap by default", async function () { csvItem.setTrait("definition", "csvString", LatLonCsv); csvItem.setTrait("definition", "activeStyle", "enum"); await csvItem.loadMapItems(); const activeStyle = csvItem.activeTableStyle; const colorColumn = activeStyle.colorColumn; expect(colorColumn).toBeDefined(); expect(colorColumn!.type).toBe(5); expect(colorColumn!.uniqueValues.values.length).toBe(6); expect(activeStyle.colorMap instanceof EnumColorMap).toBeTruthy(); expect((activeStyle.colorMap as EnumColorMap).colors.length).toBe(6); expect( (activeStyle.colorMap as EnumColorMap).colors.map((c) => c.toCssHexString() ) ).toEqual([ "#f2f3f4", "#ffb300", "#803e75", "#ff6800", "#a6bdd7", "#c10020" ]); }); it(" - uses EnumColorMap with specified colorPalette", async function () { csvItem.setTrait("definition", "csvString", LatLonCsv); csvItem.setTrait( "definition", "defaultStyle", createStratumInstance(TableStyleTraits, { color: createStratumInstance(TableColorStyleTraits, { colorPalette: "Category10" }) }) ); csvItem.setTrait("definition", "activeStyle", "enum"); await csvItem.loadMapItems(); const activeStyle = csvItem.activeTableStyle; const colorColumn = activeStyle.colorColumn; expect(colorColumn).toBeDefined(); expect(colorColumn!.type).toBe(5); expect(colorColumn!.uniqueValues.values.length).toBe(6); expect(activeStyle.colorMap instanceof EnumColorMap).toBeTruthy(); expect((activeStyle.colorMap as EnumColorMap).colors.length).toBe(6); expect( (activeStyle.colorMap as EnumColorMap).colors.map((c) => c.toCssHexString() ) ).toEqual([ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b" ]); }); }); });