UNPKG

terriajs

Version:

Geospatial data visualization platform.

552 lines (483 loc) 20.4 kB
import { http, HttpResponse } from "msw"; import CommonStrata from "../../lib/Models/Definition/CommonStrata"; import createStratumInstance from "../../lib/Models/Definition/createStratumInstance"; import CsvCatalogItem from "../../lib/Models/Catalog/CatalogItems/CsvCatalogItem"; import Terria from "../../lib/Models/Terria"; import TableColumn from "../../lib/Table/TableColumn"; import TableColumnTraits from "../../lib/Traits/TraitsClasses/Table/ColumnTraits"; import TableColumnType from "../../lib/Table/TableColumnType"; import { worker } from "../mocks/browser"; import regionMapping from "../../wwwroot/data/regionMapping.json"; describe("TableColumn", function () { let tableModel: CsvCatalogItem; beforeEach(function () { tableModel = new CsvCatalogItem("test", new Terria(), undefined); }); describe("title", function () { it("prettify titles", async () => { tableModel.setTrait( "user", "csvString", "some_title,_someOtherName,LOUDNAME, Trimmed_NAME \na,b,c" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].title).toBe("Some Title"); expect(tableModel.tableColumns[1].title).toBe("Some Other Name"); expect(tableModel.tableColumns[2].title).toBe("Loudname"); expect(tableModel.tableColumns[3].title).toBe("Trimmed Name"); }); it("correctly resolves the title", function () { const x = tableModel.addObject(CommonStrata.user, "columns", "Column0"); x?.setTrait(CommonStrata.user, "title", "Time"); const y = tableModel.addObject(CommonStrata.user, "columns", "Column1"); y?.setTrait(CommonStrata.user, "title", "Speed"); const tableColumn1 = new TableColumn(tableModel, 0); const tableColumn2 = new TableColumn(tableModel, 1); expect(tableColumn1.title).toBe("Time"); expect(tableColumn2.title).toBe("Speed"); }); it("can resolve title from the `tableModel.columnTitles` if set", function () { tableModel.setTrait(CommonStrata.user, "columnTitles", ["Time", "Speed"]); const tableColumn1 = new TableColumn(tableModel, 0); const tableColumn2 = new TableColumn(tableModel, 1); expect(tableColumn1.title).toBe("Time"); expect(tableColumn2.title).toBe("Speed"); }); }); describe("type", function () { describe("by name", function () { it("id - scalar", async () => { tableModel.setTrait(CommonStrata.user, "csvString", "id\n1\n2\n3\n4\n"); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); tableModel.setTrait(CommonStrata.user, "csvString", "ID\n1\n2\n3\n4\n"); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); tableModel.setTrait( CommonStrata.user, "csvString", "_ID_\n1\n2\n3\n4\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); tableModel.setTrait( CommonStrata.user, "csvString", "ObjectId\n1\n2\n3\n4\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); tableModel.setTrait( CommonStrata.user, "csvString", "fid\n1\n2\n3\n4\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); }); it("id - enum", async () => { tableModel.setTrait(CommonStrata.user, "csvString", "id\na\nb\nc\nd\n"); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.enum); }); it("id - text", async () => { tableModel.setTrait( CommonStrata.user, "csvString", "id\n" + [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p" ].join("\n") ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.text); }); // Re-enable when we add back TableColumnType.height // it("height", async () => { // tableModel.setTrait( // CommonStrata.user, // "csvString", // "height\n1\n2\nb\na\n" // ); // await tableModel.loadMapItems(); // expect(tableModel.tableColumns[0].type).toBe(TableColumnType.height); // }); // it("height ", async () => { // tableModel.setTrait( // CommonStrata.user, // "csvString", // "altitude,depth,height,elevation,altitude,something else\n1,1,1,1,1,1\n2,2,2,2,2,2\nb,b,b,b,b,b\na,a,a,a,a,a\n" // ); // await tableModel.loadMapItems(); // expect(tableModel.tableColumns[0].type).toBe(TableColumnType.height); // expect(tableModel.tableColumns[1].type).toBe(TableColumnType.height); // expect(tableModel.tableColumns[2].type).toBe(TableColumnType.height); // expect(tableModel.tableColumns[3].type).toBe(TableColumnType.height); // expect(tableModel.tableColumns[4].type).toBe(TableColumnType.height); // expect(tableModel.tableColumns[5].type).toBe(TableColumnType.enum); // }); it("lat/lon", async () => { tableModel.setTrait( CommonStrata.user, "csvString", "lon,long,longitude,lng,lat,latitude,something else\n1,1,1,1,1,1,1\n2,2,2,2,2,2,2\nb,b,b,b,b,b,b\na,a,a,a,a,a,a\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.longitude); expect(tableModel.tableColumns[1].type).toBe(TableColumnType.longitude); expect(tableModel.tableColumns[2].type).toBe(TableColumnType.longitude); expect(tableModel.tableColumns[3].type).toBe(TableColumnType.longitude); expect(tableModel.tableColumns[4].type).toBe(TableColumnType.latitude); expect(tableModel.tableColumns[5].type).toBe(TableColumnType.latitude); expect(tableModel.tableColumns[6].type).toBe(TableColumnType.enum); }); it("eastings / northings - scalar", async () => { tableModel.setTrait( CommonStrata.user, "csvString", "easting\n1\n2\n3\n4\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); tableModel.setTrait( CommonStrata.user, "csvString", "eastings\n1\n2\n3\n4\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); tableModel.setTrait( CommonStrata.user, "csvString", "northing\n1\n2\n3\n4\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); tableModel.setTrait( CommonStrata.user, "csvString", "northings\n1\n2\n3\n4\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.hidden); }); it("eastings / northings - enum", async () => { tableModel.setTrait( CommonStrata.user, "csvString", "easting\n1\n2\na\nb\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.enum); tableModel.setTrait( CommonStrata.user, "csvString", "eastings\n1\n2\na\nb\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.enum); tableModel.setTrait( CommonStrata.user, "csvString", "northing\n1\n2\na\nb\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.enum); tableModel.setTrait( CommonStrata.user, "csvString", "northings\n1\n2\na\nb\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.enum); }); it("date", async () => { tableModel.setTrait( CommonStrata.user, "csvString", "Start date (AEST),date,some other date,time?,year,not a year\n1,1,1,1,1,1\n2,2,2,2,2,2\nb,b,b,b,b,b\na,a,a,a,a,a\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.time); expect(tableModel.tableColumns[1].type).toBe(TableColumnType.time); expect(tableModel.tableColumns[2].type).toBe(TableColumnType.time); expect(tableModel.tableColumns[3].type).toBe(TableColumnType.time); expect(tableModel.tableColumns[4].type).toBe(TableColumnType.time); expect(tableModel.tableColumns[5].type).toBe(TableColumnType.enum); }); it("address", async () => { tableModel.setTrait( CommonStrata.user, "csvString", "address,addr,some other date,time?,year,not an address\n1,1,1,1,1,1\n2,2,2,2,2,2\nb,b,b,b,b,b\na,a,a,a,a,a\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.address); expect(tableModel.tableColumns[1].type).toBe(TableColumnType.address); expect(tableModel.tableColumns[5].type).toBe(TableColumnType.enum); }); }); describe("by values", function () { it("scalar", async () => { /** For scalar we need * - At least one number * - 10% valid numbers */ tableModel.setTrait( CommonStrata.user, "csvString", "num1,num2,num3,num4,num5,num6,num7,num8,num9\n1,1,1,1,1,1,1,1,1\n2,2,2,2,2,2,2,,1\n3,3,3,3,3,3,\n4,4,4,4,4,4,\n5,5,5,5,5,5,\n6,6,6,6,6,d,\n7,7,7,7,7,d,\n8,8,8,8,8,d,\n9,9,9,9,9,d,\n10,10,10,10,d,d,\n11,11,11,d,d,d,\n" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.scalar); // all valid expect(tableModel.tableColumns[1].type).toBe(TableColumnType.scalar); // all valid expect(tableModel.tableColumns[2].type).toBe(TableColumnType.scalar); // all valid expect(tableModel.tableColumns[3].type).toBe(TableColumnType.scalar); // 10 numbers 1 letter expect(tableModel.tableColumns[4].type).toBe(TableColumnType.text); // 9 numbers 2 letters (+ over enum thresholds) expect(tableModel.tableColumns[5].type).toBe(TableColumnType.enum); // 5 numbers 11 letters expect(tableModel.tableColumns[6].type).toBe(TableColumnType.scalar); // 2 numbers expect(tableModel.tableColumns[7].type).toBe(TableColumnType.enum); // 1 number and empty values expect(tableModel.tableColumns[8].type).toBe(TableColumnType.scalar); // 2 duplicate numbers }); it("enum", async () => { /** For enum we need * - We need more than 1 unique value (including nulls) AND one of the following: * - Only 7 unique values OR * - The number of unique values is less than 12% of total number of values (each value in the column exists 8.33 times on average) */ tableModel.setTrait( CommonStrata.user, "csvString", "7 unique values,11 unique values,15 unique values\na,a,a\na,a,a\na,b,b\nb,b,b\nb,c,c\nb,c,c\nc,d,d\nc,d,d\nc,e,e\nd,e,e\nd,f,f\nd,f,f\ne,g,g\ne,g,g\ne,h,h\nf,h,h\nf,i,i\nf,i,i\ng,j,j\ng,j,j\ng,k,k\na,a,a\na,a,a\na,b,b\nb,b,b\nb,c,c\nb,c,c\nc,d,d\nc,d,d\nc,e,e\nd,e,e\nd,f,f\nd,f,f\ne,g,g\ne,g,g\ne,h,h\nf,h,h\nf,i,i\nf,i,i\ng,j,j\ng,j,j\ng,k,k\na,a,l\na,a,m\na,b,n\nb,b,o\nb,c,f\nb,c,g\nc,d,g\nc,d,h\nc,e,h\nd,e,i\nd,f,i\nd,f,j\ne,g,j\ne,g,k\ne,h,l\nf,h,m\nf,i,n\nf,i,o\ng,j,f\ng,j,g\ng,k,g\na,a,h\na,a,h\na,b,i\nb,b,i\nb,c,j\nb,c,j\nc,d,k\nc,d,l\nc,e,m\nd,e,n\nd,f,o\nd,f,p\ne,g,g\ne,g,g\ne,h,h\nf,h,h\nf,i,i\nf,i,i\ng,j,j\ng,j,j\ng,k,k\na,a,l\na,a,m\na,b,n\nb,b,o\nb,c,f\nb,c,g\nc,d,g\nc,d,h\nc,e,h\nd,e,i\nd,f,i\nd,f,j\ne,g,j\ne,g,k\ne,h,l\nf,h,m\nf,i,n\nf,i,o\ng,j,f\ng,j,g\ng,k,g\na,a,h\na,a,h\na,b,i\nb,b,i\nb,c,j\nb,c,j\nc,d,k\nc,d,l\nc,e,m\nd,e,n\nd,f,o\nd,f,f\ne,g,g\ne,g,g\ne,h,h\nf,h,h\nf,i,i\nf,i,i\ng,j,j\ng,j,j\ng,k,k" ); await tableModel.loadMapItems(); expect(tableModel.tableColumns[0].type).toBe(TableColumnType.enum); // 7 unique values expect(tableModel.tableColumns[1].type).toBe(TableColumnType.enum); // 11 unique values (< 12% number of 126 rows = 15.12) expect(tableModel.tableColumns[2].type).toBe(TableColumnType.text); // 16 unique values (> 12% number of 126 rows = 15.12) }); }); }); describe("units", function () { it("correctly resolves the units", function () { const x = tableModel.addObject(CommonStrata.user, "columns", "Column0"); x?.setTrait(CommonStrata.user, "units", "ms"); const y = tableModel.addObject(CommonStrata.user, "columns", "Column1"); y?.setTrait(CommonStrata.user, "units", "kmph"); const tableColumn1 = new TableColumn(tableModel, 0); const tableColumn2 = new TableColumn(tableModel, 1); expect(tableColumn1.units).toBe("ms"); expect(tableColumn2.units).toBe("kmph"); }); it("can resolve unit from the `tableModel.columnUnits` if set", function () { tableModel.setTrait(CommonStrata.user, "columnUnits", ["ms", "kmph"]); const tableColumn1 = new TableColumn(tableModel, 0); const tableColumn2 = new TableColumn(tableModel, 1); expect(tableColumn1.units).toBe("ms"); expect(tableColumn2.units).toBe("kmph"); }); }); describe("valuesAsDates", function () { beforeEach(function () { worker.use( http.get("*/build/TerriaJS/data/regionMapping.json", () => HttpResponse.json(regionMapping) ) ); }); it("defaults to dd/mm/yyyy dates", async function () { tableModel.setTrait( CommonStrata.user, "csvString", "date\n01/03/2004\n12/12/1999\n" ); await tableModel.loadMapItems(); const tableColumn1 = new TableColumn(tableModel, 0); expect( tableColumn1.valuesAsDates.values.map((d) => d && d.toISOString()) ).toEqual( [new Date("2004/03/01"), new Date("1999/12/12")].map((d) => d.toISOString() ) ); }); it("can convert d-m-yy dates", async function () { tableModel.setTrait( CommonStrata.user, "csvString", "date\n15-7-95\n3-7-20\n" ); await tableModel.loadMapItems(); const tableColumn1 = new TableColumn(tableModel, 0); expect( tableColumn1.valuesAsDates.values.map((d) => d && d.toISOString()) ).toEqual( [new Date("1995/07/15"), new Date("2020/07/03")].map((d) => d.toISOString() ) ); }); it("converts all dates to mm/dd/yyyy in a column if one doesn't fit dd/mm/yyyy", async function () { tableModel.setTrait( CommonStrata.user, "csvString", "date\n06/20/2004\n03/10/1999\n" ); await tableModel.loadMapItems(); const tableColumn1 = new TableColumn(tableModel, 0); expect( tableColumn1.valuesAsDates.values.map((d) => d && d.toISOString()) ).toEqual( [new Date("2004/06/20"), new Date("1999/03/10")].map((d) => d.toISOString() ) ); }); it("can convert yyyy-Qx dates", async function () { tableModel.setTrait( CommonStrata.user, "csvString", "TIME_PERIOD,OBS_VALUE\n1983-Q2,-0.6\n1983-Q3,-3.2\n1983-Q4,0.9\n1984-Q1,-1.7\n1984-Q2,3.6\n1984-Q3,-1.1\n1984-Q4,3\n1985-Q1,1.1" ); await tableModel.loadMapItems(); const tableColumn1 = new TableColumn(tableModel, 0); expect( tableColumn1.valuesAsDates.values.map((d) => d && d.toISOString()) ).toEqual( [ new Date("1983/04/01"), new Date("1983/07/01"), new Date("1983/10/01"), new Date("1984/01/01"), new Date("1984/04/01"), new Date("1984/07/01"), new Date("1984/10/01"), new Date("1985/01/01") ].map((d) => d.toISOString()) ); }); it("attempts to convert all dates using new Date if one date fails parsing with dd/mm/yyyy and mm/dd/yyyy", async function () { tableModel.setTrait( CommonStrata.user, "csvString", "date\n06/06/2004\n03/10/1999\nNot a date" ); await tableModel.loadMapItems(); const tableColumn1 = new TableColumn(tableModel, 0); expect( tableColumn1.valuesAsDates.values.map((d) => d && d.toISOString()) ).toEqual([ ...[new Date("2004/06/06"), new Date("1999/03/10")].map((d) => d.toISOString() ), null ]); }); }); describe("column transformation", function () { beforeEach(function () { worker.use( http.get("*/build/TerriaJS/data/regionMapping.json", () => HttpResponse.json(regionMapping) ) ); }); it("simple expression", async function () { tableModel.setTrait(CommonStrata.user, "csvString", "num\n1\n2\n3\n4\n"); tableModel.setTrait(CommonStrata.user, "columns", [ createStratumInstance(TableColumnTraits, { name: "num", transformation: { expression: `x+10`, dependencies: [] } }) ]); await tableModel.loadMapItems(); const tableColumn1 = new TableColumn(tableModel, 0); expect(tableColumn1.values).toEqual(["1", "2", "3", "4"]); expect(tableColumn1.valuesAsNumbers.values).toEqual([11, 12, 13, 14]); }); it("expression with dependency", async function () { tableModel.setTrait( CommonStrata.user, "csvString", "num,num2,num3\n1,11,21\n2,12,22\n3,13,23\n4,14,24\n" ); tableModel.setTrait(CommonStrata.user, "columns", [ createStratumInstance(TableColumnTraits, { name: "num", transformation: { expression: `x*num2`, dependencies: ["num2"] } }) ]); await tableModel.loadMapItems(); const tableColumn1 = new TableColumn(tableModel, 0); expect(tableColumn1.values).toEqual(["1", "2", "3", "4"]); const tableColumn2 = new TableColumn(tableModel, 1); expect(tableColumn2.values).toEqual(["11", "12", "13", "14"]); expect(tableColumn1.valuesAsNumbers.values).toEqual([ 1 * 11, 2 * 12, 3 * 13, 4 * 14 ]); }); it("expressions with dependencies (nested)", async function () { tableModel.setTrait( CommonStrata.user, "csvString", "num,num2,num3\n1,11,21\n2,12,22\n3,13,23\n4,14,24\n" ); tableModel.setTrait(CommonStrata.user, "columns", [ createStratumInstance(TableColumnTraits, { name: "num", transformation: { expression: `x*num2`, dependencies: ["num2"] } }), createStratumInstance(TableColumnTraits, { name: "num2", transformation: { expression: `x*10`, dependencies: [""] } }), createStratumInstance(TableColumnTraits, { name: "num3", transformation: { // Note this would make num3 = x * [num * (num2*10)] * (num2*10) expression: `x*num*num2`, dependencies: ["num", "num2"] } }) ]); await tableModel.loadMapItems(); const tableColumn3 = new TableColumn(tableModel, 2); expect(tableColumn3.values).toEqual(["21", "22", "23", "24"]); expect(tableColumn3.valuesAsNumbers.values).toEqual([ 1 * 11 * 10 * 11 * 10 * 21, 2 * 12 * 10 * 12 * 10 * 22, 3 * 13 * 10 * 13 * 10 * 23, 4 * 14 * 10 * 14 * 10 * 24 ]); }); }); });