Reformat all files with prettier

This commit is contained in:
Pieter Vander Vennet 2022-09-08 21:40:48 +02:00
parent e22d189376
commit b541d3eab4
382 changed files with 50893 additions and 35566 deletions

View file

@ -1,16 +1,17 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import { describe } from "mocha"
import { expect } from "chai"
describe("TestSuite", () => {
describe("function under test", () => {
it("should work", () => {
expect("abc").eq("abc")
expect("abc").eq("abc")
})
})
})
it("global test", async() => {
it("global test", async () => {
expect("abc").eq("abc")
expect(() => {throw "hi"}).throws(/hi/)
})
expect(() => {
throw "hi"
}).throws(/hi/)
})

View file

@ -1,5 +1,5 @@
import {describe} from 'mocha'
import {exec} from "child_process";
import { describe } from "mocha"
import { exec } from "child_process"
/**
*
@ -8,33 +8,51 @@ import {exec} from "child_process";
* @private
*/
function detectInCode(forbidden: string, reason: string) {
const excludedDirs = [
".git",
"node_modules",
"dist",
".cache",
".parcel-cache",
"assets",
"vendor",
".idea/",
]
const excludedDirs = [".git", "node_modules", "dist", ".cache", ".parcel-cache", "assets", "vendor", ".idea/"]
exec(
'grep -n "' +
forbidden +
'" -r . ' +
excludedDirs.map((d) => "--exclude-dir=" + d).join(" "),
(error, stdout, stderr) => {
if (error?.message?.startsWith("Command failed: grep")) {
console.warn("Command failed!")
return
}
if (error !== null) {
throw error
}
if (stderr !== "") {
throw stderr
}
exec("grep -n \"" + forbidden + "\" -r . " + excludedDirs.map(d => "--exclude-dir=" + d).join(" "), ((error, stdout, stderr) => {
if (error?.message?.startsWith("Command failed: grep")) {
console.warn("Command failed!")
return;
const found = stdout
.split("\n")
.filter((s) => s !== "")
.filter((s) => !s.startsWith("./test/"))
if (found.length > 0) {
throw `Found a '${forbidden}' at \n ${found.join("\n ")}.\n ${reason}`
}
}
if (error !== null) {
throw error
}
if (stderr !== "") {
throw stderr
}
const found = stdout.split("\n").filter(s => s !== "").filter(s => !s.startsWith("./test/"));
if (found.length > 0) {
throw `Found a '${forbidden}' at \n ${found.join("\n ")}.\n ${reason}`
}
}))
)
}
describe("Code quality", () => {
it("should not contain reverse", () => {
detectInCode("reverse()", "Reverse is stateful and changes the source list. This often causes subtle bugs")
detectInCode(
"reverse()",
"Reverse is stateful and changes the source list. This often causes subtle bugs"
)
})
it("should not contain 'constructor.name'", () => {
@ -42,8 +60,9 @@ describe("Code quality", () => {
})
it("should not contain 'innerText'", () => {
detectInCode("innerText", "innerText is not allowed as it is not testable with fakeDom. Use 'textContent' instead.")
detectInCode(
"innerText",
"innerText is not allowed as it is not testable with fakeDom. Use 'textContent' instead."
)
})
})

View file

@ -1,87 +1,83 @@
import {expect} from 'chai'
import {Utils} from "../../../Utils";
import UserRelatedState from "../../../Logic/State/UserRelatedState";
import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig";
import SelectedElementTagsUpdater from "../../../Logic/Actors/SelectedElementTagsUpdater";
import { expect } from "chai"
import { Utils } from "../../../Utils"
import UserRelatedState from "../../../Logic/State/UserRelatedState"
import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig"
import SelectedElementTagsUpdater from "../../../Logic/Actors/SelectedElementTagsUpdater"
import * as bookcaseJson from "../../../assets/generated/themes/bookcases.json"
import {UIEventSource} from "../../../Logic/UIEventSource";
import Loc from "../../../Models/Loc";
import SelectedFeatureHandler from "../../../Logic/Actors/SelectedFeatureHandler";
import {ElementStorage} from "../../../Logic/ElementStorage";
import { UIEventSource } from "../../../Logic/UIEventSource"
import Loc from "../../../Models/Loc"
import SelectedFeatureHandler from "../../../Logic/Actors/SelectedFeatureHandler"
import { ElementStorage } from "../../../Logic/ElementStorage"
const latestTags = {
"amenity": "public_bookcase",
"books": "children;adults",
"capacity": "25",
"description": "Deze boekenruilkast vindt je recht tegenover de Pim Pam Poem",
amenity: "public_bookcase",
books: "children;adults",
capacity: "25",
description: "Deze boekenruilkast vindt je recht tegenover de Pim Pam Poem",
"image:0": "https://i.imgur.com/Z8a69UG.jpg",
"name": "Stubbekwartier-buurtbibliotheek",
"nobrand": "yes",
"opening_hours": "24/7",
"operator": "Huisbewoner",
"public_bookcase:type": "reading_box"
name: "Stubbekwartier-buurtbibliotheek",
nobrand: "yes",
opening_hours: "24/7",
operator: "Huisbewoner",
"public_bookcase:type": "reading_box",
}
Utils.injectJsonDownloadForTests(
"https://www.openstreetmap.org/api/0.6/node/5568693115",
{
"version": "0.6",
"generator": "CGImap 0.8.5 (1815943 spike-06.openstreetmap.org)",
"copyright": "OpenStreetMap and contributors",
"attribution": "http://www.openstreetmap.org/copyright",
"license": "http://opendatacommons.org/licenses/odbl/1-0/",
"elements": [{
"type": "node",
"id": 5568693115,
"lat": 51.2179199,
"lon": 3.2154662,
"timestamp": "2021-08-21T16:22:55Z",
"version": 6,
"changeset": 110034454,
"user": "Pieter Vander Vennet",
"uid": 3818858,
"tags": latestTags
}]
}
)
Utils.injectJsonDownloadForTests("https://www.openstreetmap.org/api/0.6/node/5568693115", {
version: "0.6",
generator: "CGImap 0.8.5 (1815943 spike-06.openstreetmap.org)",
copyright: "OpenStreetMap and contributors",
attribution: "http://www.openstreetmap.org/copyright",
license: "http://opendatacommons.org/licenses/odbl/1-0/",
elements: [
{
type: "node",
id: 5568693115,
lat: 51.2179199,
lon: 3.2154662,
timestamp: "2021-08-21T16:22:55Z",
version: 6,
changeset: 110034454,
user: "Pieter Vander Vennet",
uid: 3818858,
tags: latestTags,
},
],
})
it("should download the latest version", () => {
const state = new UserRelatedState(new LayoutConfig(<any> bookcaseJson, true))
it("should download the latest version", () => {
const state = new UserRelatedState(new LayoutConfig(<any>bookcaseJson, true))
const feature = {
"type": "Feature",
"id": "node/5568693115",
"properties": {
"amenity": "public_bookcase",
"books": "children;adults",
"capacity": "25",
"description": "Deze boekenruilkast vindt je recht tegenover de Pim Pam Poem",
type: "Feature",
id: "node/5568693115",
properties: {
amenity: "public_bookcase",
books: "children;adults",
capacity: "25",
description: "Deze boekenruilkast vindt je recht tegenover de Pim Pam Poem",
"image:0": "https://i.imgur.com/Z8a69UG.jpg",
"name": "OUTDATED NAME",
"nobrand": "yes",
"opening_hours": "24/7",
"operator": "Huisbewoner",
name: "OUTDATED NAME",
nobrand: "yes",
opening_hours: "24/7",
operator: "Huisbewoner",
"public_bookcase:type": "reading_box",
"id": "node/5568693115",
"_lat": "51.2179199",
"_lon": "3.2154662",
"fixme": "SOME FIXME"
id: "node/5568693115",
_lat: "51.2179199",
_lon: "3.2154662",
fixme: "SOME FIXME",
},
"geometry": {
"type": "Point",
"coordinates": [
3.2154662,
51.2179199
]
geometry: {
type: "Point",
coordinates: [3.2154662, 51.2179199],
},
"bbox": {
"maxLat": 51.2179199,
"maxLon": 3.2154662,
"minLat": 51.2179199,
"minLon": 3.2154662
bbox: {
maxLat: 51.2179199,
maxLon: 3.2154662,
minLat: 51.2179199,
minLon: 3.2154662,
},
"_lon": 3.2154662,
"_lat": 51.2179199
_lon: 3.2154662,
_lat: 51.2179199,
}
state.allElements.addOrGetElement(feature)
SelectedElementTagsUpdater.installCallback(state)
@ -96,7 +92,6 @@ it("should download the latest version", () => {
expect(feature.properties.name).deep.equal("Stubbekwartier-buurtbibliotheek")
// The fixme should be removed
expect(feature.properties.fixme).deep.equal(undefined)
})
it("Hash without selected element should download geojson from OSM-API", async () => {
const hash = new UIEventSource("node/5568693115")
@ -104,11 +99,10 @@ it("Hash without selected element should download geojson from OSM-API", async (
const loc = new UIEventSource<Loc>({
lat: 0,
lon: 0,
zoom: 0
zoom: 0,
})
loc.addCallback(_ => {
loc.addCallback((_) => {
expect(selected.data.properties.id).deep.equal("node/5568693115")
expect(loc.data.zoom).deep.equal(14)
expect(loc.data.lat).deep.equal(51.2179199)
@ -119,8 +113,6 @@ it("Hash without selected element should download geojson from OSM-API", async (
allElements: new ElementStorage(),
featurePipeline: undefined,
locationControl: loc,
layoutToUse: undefined
layoutToUse: undefined,
})
})
})

View file

@ -1,209 +1,126 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import CreateMultiPolygonWithPointReuseAction from "../../../Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction";
import {Tag} from "../../../Logic/Tags/Tag";
import {Changes} from "../../../Logic/Osm/Changes";
import { describe } from "mocha"
import { expect } from "chai"
import CreateMultiPolygonWithPointReuseAction from "../../../Logic/Osm/Actions/CreateMultiPolygonWithPointReuseAction"
import { Tag } from "../../../Logic/Tags/Tag"
import { Changes } from "../../../Logic/Osm/Changes"
describe("CreateMultiPolygonWithPointReuseAction", () => {
it("should produce a correct changeset", () => {
async () => {
const feature = {
"type": "Feature",
"properties": {
"osm_id": "41097039",
"size_grb_building": "1374.89",
"addr:housenumber": "53",
"addr:street": "Startelstraat",
"building": "house",
"source:geometry:entity": "Gbg",
"source:geometry:date": "2014-04-28",
"source:geometry:oidn": "150044",
"source:geometry:uidn": "5403181",
"H_DTM_MIN": "50.35",
"H_DTM_GEM": "50.97",
"H_DSM_MAX": "59.40",
"H_DSM_P99": "59.09",
"HN_MAX": "8.43",
"HN_P99": "8.12",
"detection_method": "derived from OSM landuse: farmyard",
"auto_target_landuse": "farmyard",
"size_source_landuse": "8246.28",
"auto_building": "farm",
"id": "41097039",
"_lat": "50.84633355000016",
"_lon": "5.262964150000011",
"_layer": "grb",
"_length": "185.06002152312757",
"_length:km": "0.2",
"_now:date": "2022-02-22",
"_now:datetime": "2022-02-22 10:15:51",
"_loaded:date": "2022-02-22",
"_loaded:datetime": "2022-02-22 10:15:51",
"_geometry:type": "Polygon",
"_intersects_with_other_features": "",
"_country": "be",
"_overlaps_with_buildings": "[]",
"_overlap_percentage": "null",
"_grb_date": "2014-04-28",
"_grb_ref": "Gbg/150044",
"_building:min_level": "",
"_surface": "548.1242491529038",
"_surface:ha": "0",
"_reverse_overlap_percentage": "null",
"_imported_osm_object_found": "false",
"_imported_osm_still_fresh": "false",
"_target_building_type": "house"
},
"geometry": {
"type": "Polygon",
"coordinates": <[number, number][][]>[
[
[
5.262684300000043,
50.84624409999995
],
[
5.262777500000024,
50.84620759999988
],
[
5.262798899999998,
50.84621390000019
],
[
5.262999799999994,
50.84619519999999
],
[
5.263107500000007,
50.84618920000014
],
[
5.263115,
50.84620990000026
],
[
5.26310279999998,
50.84623050000014
],
[
5.263117999999977,
50.846247400000166
],
[
5.263174599999989,
50.84631019999971
],
[
5.263166999999989,
50.84631459999995
],
[
5.263243999999979,
50.84640239999989
],
[
5.2631607000000065,
50.84643459999996
],
[
5.26313309999997,
50.84640089999985
],
[
5.262907499999996,
50.84647790000018
],
[
5.2628939999999576,
50.846463699999774
],
[
5.262872100000033,
50.846440700000294
],
[
5.262784699999991,
50.846348899999924
],
[
5.262684300000043,
50.84624409999995
]
],
[
[
5.262801899999976,
50.84623269999982
],
[
5.2629535000000285,
50.84638830000012
],
[
5.263070700000018,
50.84634720000008
],
[
5.262998000000025,
50.84626279999982
],
[
5.263066799999966,
50.84623959999975
],
[
5.263064000000004,
50.84623330000007
],
[
5.263009599999997,
50.84623730000026
],
[
5.263010199999956,
50.84621629999986
],
[
5.262801899999976,
50.84623269999982
]
]
]
},
}
const innerRings = [...feature.geometry.coordinates]
innerRings.splice(0, 1)
const action = new CreateMultiPolygonWithPointReuseAction(
[new Tag("building", "yes")],
feature.geometry.coordinates[0],
innerRings,
undefined,
[],
"import"
)
const descriptions = await action.Perform(new Changes())
const ways= descriptions.filter(d => d.type === "way")
expect(ways[0].id == -18, "unexpected id").true
expect(ways[1].id == -27, "unexpected id").true
const outer = ways[0].changes["coordinates"]
expect(outer).deep.equal(feature.geometry.coordinates[0])
const inner = ways[1].changes["coordinates"]
expect(inner).deep.equal(feature.geometry.coordinates[1])
const members = <{type: string, role: string, ref: number}[]> descriptions.find(d => d.type === "relation").changes["members"]
expect(members[0].role, "incorrect role").eq("outer")
expect(members[1].role, "incorrect role").eq("inner")
expect(members[0].type , "incorrect type").eq("way")
expect(members[1].type , "incorrect type").eq("way")
expect(members[0].ref, "incorrect id").eq(-18)
expect(members[1].ref , "incorrect id").eq(-27)
it("should produce a correct changeset", () => {
;async () => {
const feature = {
type: "Feature",
properties: {
osm_id: "41097039",
size_grb_building: "1374.89",
"addr:housenumber": "53",
"addr:street": "Startelstraat",
building: "house",
"source:geometry:entity": "Gbg",
"source:geometry:date": "2014-04-28",
"source:geometry:oidn": "150044",
"source:geometry:uidn": "5403181",
H_DTM_MIN: "50.35",
H_DTM_GEM: "50.97",
H_DSM_MAX: "59.40",
H_DSM_P99: "59.09",
HN_MAX: "8.43",
HN_P99: "8.12",
detection_method: "derived from OSM landuse: farmyard",
auto_target_landuse: "farmyard",
size_source_landuse: "8246.28",
auto_building: "farm",
id: "41097039",
_lat: "50.84633355000016",
_lon: "5.262964150000011",
_layer: "grb",
_length: "185.06002152312757",
"_length:km": "0.2",
"_now:date": "2022-02-22",
"_now:datetime": "2022-02-22 10:15:51",
"_loaded:date": "2022-02-22",
"_loaded:datetime": "2022-02-22 10:15:51",
"_geometry:type": "Polygon",
_intersects_with_other_features: "",
_country: "be",
_overlaps_with_buildings: "[]",
_overlap_percentage: "null",
_grb_date: "2014-04-28",
_grb_ref: "Gbg/150044",
"_building:min_level": "",
_surface: "548.1242491529038",
"_surface:ha": "0",
_reverse_overlap_percentage: "null",
_imported_osm_object_found: "false",
_imported_osm_still_fresh: "false",
_target_building_type: "house",
},
geometry: {
type: "Polygon",
coordinates: <[number, number][][]>[
[
[5.262684300000043, 50.84624409999995],
[5.262777500000024, 50.84620759999988],
[5.262798899999998, 50.84621390000019],
[5.262999799999994, 50.84619519999999],
[5.263107500000007, 50.84618920000014],
[5.263115, 50.84620990000026],
[5.26310279999998, 50.84623050000014],
[5.263117999999977, 50.846247400000166],
[5.263174599999989, 50.84631019999971],
[5.263166999999989, 50.84631459999995],
[5.263243999999979, 50.84640239999989],
[5.2631607000000065, 50.84643459999996],
[5.26313309999997, 50.84640089999985],
[5.262907499999996, 50.84647790000018],
[5.2628939999999576, 50.846463699999774],
[5.262872100000033, 50.846440700000294],
[5.262784699999991, 50.846348899999924],
[5.262684300000043, 50.84624409999995],
],
[
[5.262801899999976, 50.84623269999982],
[5.2629535000000285, 50.84638830000012],
[5.263070700000018, 50.84634720000008],
[5.262998000000025, 50.84626279999982],
[5.263066799999966, 50.84623959999975],
[5.263064000000004, 50.84623330000007],
[5.263009599999997, 50.84623730000026],
[5.263010199999956, 50.84621629999986],
[5.262801899999976, 50.84623269999982],
],
],
},
}
})
})
const innerRings = [...feature.geometry.coordinates]
innerRings.splice(0, 1)
const action = new CreateMultiPolygonWithPointReuseAction(
[new Tag("building", "yes")],
feature.geometry.coordinates[0],
innerRings,
undefined,
[],
"import"
)
const descriptions = await action.Perform(new Changes())
const ways = descriptions.filter((d) => d.type === "way")
expect(ways[0].id == -18, "unexpected id").true
expect(ways[1].id == -27, "unexpected id").true
const outer = ways[0].changes["coordinates"]
expect(outer).deep.equal(feature.geometry.coordinates[0])
const inner = ways[1].changes["coordinates"]
expect(inner).deep.equal(feature.geometry.coordinates[1])
const members = <{ type: string; role: string; ref: number }[]>(
descriptions.find((d) => d.type === "relation").changes["members"]
)
expect(members[0].role, "incorrect role").eq("outer")
expect(members[1].role, "incorrect role").eq("inner")
expect(members[0].type, "incorrect type").eq("way")
expect(members[1].type, "incorrect type").eq("way")
expect(members[0].ref, "incorrect id").eq(-18)
expect(members[1].ref, "incorrect id").eq(-27)
}
})
})

View file

@ -1,57 +1,52 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {ExtraFuncParams, ExtraFunctions} from "../../Logic/ExtraFunctions";
import {OsmFeature} from "../../Models/OsmFeature";
import { describe } from "mocha"
import { expect } from "chai"
import { ExtraFuncParams, ExtraFunctions } from "../../Logic/ExtraFunctions"
import { OsmFeature } from "../../Models/OsmFeature"
describe("OverlapFunc", () => {
it("should give doors on the edge", () => {
const door: OsmFeature = {
"type": "Feature",
"id": "node/9909268725",
"properties": {
"automatic_door": "no",
"door": "hinged",
"indoor": "door",
type: "Feature",
id: "node/9909268725",
properties: {
automatic_door: "no",
door: "hinged",
indoor: "door",
"kerb:height": "0 cm",
"width": "1",
"id": "node/9909268725",
width: "1",
id: "node/9909268725",
},
"geometry": {
"type": "Point",
"coordinates": [
4.3494436,
50.8657928
]
geometry: {
type: "Point",
coordinates: [4.3494436, 50.8657928],
},
}
const hermanTeirlinck = {
"type": "Feature",
"id": "way/444059131",
"properties": {
"timestamp": "2022-07-27T15:15:01Z",
"version": 27,
"changeset": 124146283,
"user": "Pieter Vander Vennet",
"uid": 3818858,
type: "Feature",
id: "way/444059131",
properties: {
timestamp: "2022-07-27T15:15:01Z",
version: 27,
changeset: 124146283,
user: "Pieter Vander Vennet",
uid: 3818858,
"addr:city": "Bruxelles - Brussel",
"addr:housenumber": "88",
"addr:postcode": "1000",
"addr:street": "Avenue du Port - Havenlaan",
"building": "government",
building: "government",
"building:levels": "5",
"name": "Herman Teirlinckgebouw",
"operator": "Vlaamse overheid",
"wikidata": "Q47457146",
"wikipedia": "nl:Herman Teirlinckgebouw",
"id": "way/444059131",
"_backend": "https://www.openstreetmap.org",
"_lat": "50.86622355",
"_lon": "4.3501212",
"_layer": "walls_and_buildings",
"_length": "380.5933566256343",
name: "Herman Teirlinckgebouw",
operator: "Vlaamse overheid",
wikidata: "Q47457146",
wikipedia: "nl:Herman Teirlinckgebouw",
id: "way/444059131",
_backend: "https://www.openstreetmap.org",
_lat: "50.86622355",
_lon: "4.3501212",
_layer: "walls_and_buildings",
_length: "380.5933566256343",
"_length:km": "0.4",
"_now:date": "2022-07-29",
"_now:datetime": "2022-07-29 14:19:25",
@ -61,183 +56,72 @@ describe("OverlapFunc", () => {
"_last_edit:contributor:uid": 3818858,
"_last_edit:changeset": 124146283,
"_last_edit:timestamp": "2022-07-27T15:15:01Z",
"_version_number": 27,
_version_number: 27,
"_geometry:type": "Polygon",
"_surface": "7461.252251355437",
_surface: "7461.252251355437",
"_surface:ha": "0.7",
"_country": "be"
_country: "be",
},
"geometry": {
"type": "Polygon",
"coordinates": [
geometry: {
type: "Polygon",
coordinates: [
[
[
4.3493369,
50.8658274
],
[
4.3493393,
50.8658266
],
[
4.3494436,
50.8657928
],
[
4.3495272,
50.8657658
],
[
4.349623,
50.8657348
],
[
4.3497442,
50.8656956
],
[
4.3498441,
50.8656632
],
[
4.3500768,
50.8655878
],
[
4.3501619,
50.8656934
],
[
4.3502113,
50.8657551
],
[
4.3502729,
50.8658321
],
[
4.3503063,
50.8658737
],
[
4.3503397,
50.8659153
],
[
4.3504159,
50.8660101
],
[
4.3504177,
50.8660123
],
[
4.3504354,
50.8660345
],
[
4.3505348,
50.8661584
],
[
4.3504935,
50.866172
],
[
4.3506286,
50.8663405
],
[
4.3506701,
50.8663271
],
[
4.3508563,
50.8665592
],
[
4.3509055,
50.8666206
],
[
4.3506278,
50.8667104
],
[
4.3504502,
50.8667675
],
[
4.3503132,
50.8668115
],
[
4.3502162,
50.8668427
],
[
4.3501645,
50.8668593
],
[
4.3499296,
50.8665664
],
[
4.3498821,
50.8665073
],
[
4.3498383,
50.8664527
],
[
4.3498126,
50.8664207
],
[
4.3497459,
50.8663376
],
[
4.3497227,
50.8663086
],
[
4.3496517,
50.8662201
],
[
4.3495158,
50.8660507
],
[
4.3493369,
50.8658274
]
]
]
[4.3493369, 50.8658274],
[4.3493393, 50.8658266],
[4.3494436, 50.8657928],
[4.3495272, 50.8657658],
[4.349623, 50.8657348],
[4.3497442, 50.8656956],
[4.3498441, 50.8656632],
[4.3500768, 50.8655878],
[4.3501619, 50.8656934],
[4.3502113, 50.8657551],
[4.3502729, 50.8658321],
[4.3503063, 50.8658737],
[4.3503397, 50.8659153],
[4.3504159, 50.8660101],
[4.3504177, 50.8660123],
[4.3504354, 50.8660345],
[4.3505348, 50.8661584],
[4.3504935, 50.866172],
[4.3506286, 50.8663405],
[4.3506701, 50.8663271],
[4.3508563, 50.8665592],
[4.3509055, 50.8666206],
[4.3506278, 50.8667104],
[4.3504502, 50.8667675],
[4.3503132, 50.8668115],
[4.3502162, 50.8668427],
[4.3501645, 50.8668593],
[4.3499296, 50.8665664],
[4.3498821, 50.8665073],
[4.3498383, 50.8664527],
[4.3498126, 50.8664207],
[4.3497459, 50.8663376],
[4.3497227, 50.8663086],
[4.3496517, 50.8662201],
[4.3495158, 50.8660507],
[4.3493369, 50.8658274],
],
],
},
bbox: {
maxLat: 50.8668593,
maxLon: 4.3509055,
minLat: 50.8655878,
minLon: 4.3493369,
},
"bbox": {
"maxLat": 50.8668593,
"maxLon": 4.3509055,
"minLat": 50.8655878,
"minLon": 4.3493369
}
}
const params: ExtraFuncParams = {
getFeatureById: id => undefined,
getFeatureById: (id) => undefined,
getFeaturesWithin: () => [[door]],
memberships: undefined
memberships: undefined,
}
ExtraFunctions.FullPatchFeature(params, hermanTeirlinck)
const overlap = (<any>hermanTeirlinck).overlapWith("*")
console.log(JSON.stringify(overlap))
expect(overlap[0].feat == door).true
})
})
})

View file

@ -1,234 +1,111 @@
import {describe} from 'mocha'
import OsmFeatureSource from "../../../Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource";
import {UIEventSource} from "../../../Logic/UIEventSource";
import ScriptUtils from "../../../scripts/ScriptUtils";
import FilteredLayer, {FilterState} from "../../../Models/FilteredLayer";
import {Tiles} from "../../../Models/TileRange";
import {readFileSync} from "fs";
import {Utils} from "../../../Utils";
import {Tag} from "../../../Logic/Tags/Tag";
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
import {expect} from "chai";
import { describe } from "mocha"
import OsmFeatureSource from "../../../Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource"
import { UIEventSource } from "../../../Logic/UIEventSource"
import ScriptUtils from "../../../scripts/ScriptUtils"
import FilteredLayer, { FilterState } from "../../../Models/FilteredLayer"
import { Tiles } from "../../../Models/TileRange"
import { readFileSync } from "fs"
import { Utils } from "../../../Utils"
import { Tag } from "../../../Logic/Tags/Tag"
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
import { expect } from "chai"
const expected = {
"type": "Feature",
"id": "relation/5759328",
"properties": {
"timestamp": "2022-06-10T00:46:55Z",
"version": 6,
"changeset": 122187206,
"user": "Pieter Vander Vennet",
"uid": 3818858,
"amenity": "school",
type: "Feature",
id: "relation/5759328",
properties: {
timestamp: "2022-06-10T00:46:55Z",
version: 6,
changeset: 122187206,
user: "Pieter Vander Vennet",
uid: 3818858,
amenity: "school",
"isced:2011:level": "vocational_lower_secondary;vocational_upper_secondary",
"name": "Koninklijk Technisch Atheneum Pro Technica",
name: "Koninklijk Technisch Atheneum Pro Technica",
"school:gender": "mixed",
"type": "multipolygon",
"website": "http://ktahalle.be/",
"id": "relation/5759328",
"_backend":"https://osm.org"
type: "multipolygon",
website: "http://ktahalle.be/",
id: "relation/5759328",
_backend: "https://osm.org",
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
geometry: {
type: "MultiPolygon",
coordinates: [
[
[
[
4.2461832,
50.7335751
],
[
4.2463167,
50.7336785
],
[
4.2463473,
50.7337021
],
[
4.2464497,
50.7337814
],
[
4.2471698,
50.7343389
],
[
4.2469541,
50.7344768
],
[
4.2467571,
50.7346116
],
[
4.2467727,
50.7346199
],
[
4.2465714,
50.7347511
],
[
4.2462398,
50.7349687
],
[
4.2453546,
50.734601
],
[
4.2451895,
50.7345103
],
[
4.2448867,
50.7342629
],
[
4.244899,
50.7342069
],
[
4.2461832,
50.7335751
]
]
[4.2461832, 50.7335751],
[4.2463167, 50.7336785],
[4.2463473, 50.7337021],
[4.2464497, 50.7337814],
[4.2471698, 50.7343389],
[4.2469541, 50.7344768],
[4.2467571, 50.7346116],
[4.2467727, 50.7346199],
[4.2465714, 50.7347511],
[4.2462398, 50.7349687],
[4.2453546, 50.734601],
[4.2451895, 50.7345103],
[4.2448867, 50.7342629],
[4.244899, 50.7342069],
[4.2461832, 50.7335751],
],
],
[
[
[
4.2444209,
50.7353737
],
[
4.2439986,
50.7352034
],
[
4.2440303,
50.7351755
],
[
4.2440602,
50.7351058
],
[
4.2439776,
50.7350326
],
[
4.2439558,
50.7350132
],
[
4.2438246,
50.7348961
],
[
4.2437848,
50.73486
],
[
4.2436555,
50.7347455
],
[
4.2435905,
50.734689
],
[
4.2435494,
50.7346601
],
[
4.2435038,
50.7346256
],
[
4.2434769,
50.7346026
],
[
4.2430948,
50.734275
],
[
4.2427978,
50.7340052
],
[
4.2430556,
50.7338391
],
[
4.2438957,
50.7334942
],
[
4.2440204,
50.7336368
],
[
4.2442806,
50.7338922
],
[
4.2444173,
50.7340119
],
[
4.2447379,
50.7342925
],
[
4.2450107,
50.7345294
],
[
4.2450236,
50.7346021
],
[
4.2449643,
50.7347019
],
[
4.244711,
50.7350821
],
[
4.2444209,
50.7353737
]
]
]
]
}
[4.2444209, 50.7353737],
[4.2439986, 50.7352034],
[4.2440303, 50.7351755],
[4.2440602, 50.7351058],
[4.2439776, 50.7350326],
[4.2439558, 50.7350132],
[4.2438246, 50.7348961],
[4.2437848, 50.73486],
[4.2436555, 50.7347455],
[4.2435905, 50.734689],
[4.2435494, 50.7346601],
[4.2435038, 50.7346256],
[4.2434769, 50.7346026],
[4.2430948, 50.734275],
[4.2427978, 50.7340052],
[4.2430556, 50.7338391],
[4.2438957, 50.7334942],
[4.2440204, 50.7336368],
[4.2442806, 50.7338922],
[4.2444173, 50.7340119],
[4.2447379, 50.7342925],
[4.2450107, 50.7345294],
[4.2450236, 50.7346021],
[4.2449643, 50.7347019],
[4.244711, 50.7350821],
[4.2444209, 50.7353737],
],
],
],
},
}
function test(done: () => void){
let fetchedTile = undefined;
const neededTiles = new UIEventSource<number[]>([Tiles.tile_index(17, 67081, 44033)]);
function test(done: () => void) {
let fetchedTile = undefined
const neededTiles = new UIEventSource<number[]>([Tiles.tile_index(17, 67081, 44033)])
new OsmFeatureSource({
allowedFeatures: new Tag("amenity", "school"),
handleTile: tile => {
handleTile: (tile) => {
fetchedTile = tile
const data = tile.features.data[0].feature
expect(data.properties).deep.eq({
id: 'relation/5759328', timestamp: '2022-06-10T00:46:55Z',
id: "relation/5759328",
timestamp: "2022-06-10T00:46:55Z",
version: 6,
changeset: 122187206,
user: 'Pieter Vander Vennet',
user: "Pieter Vander Vennet",
uid: 3818858,
amenity: 'school',
'isced:2011:level': 'vocational_lower_secondary;vocational_upper_secondary',
name: 'Koninklijk Technisch Atheneum Pro Technica',
'school:gender': 'mixed',
type: 'multipolygon',
website: 'http://ktahalle.be/',
_backend: 'https://osm.org'
amenity: "school",
"isced:2011:level": "vocational_lower_secondary;vocational_upper_secondary",
name: "Koninklijk Technisch Atheneum Pro Technica",
"school:gender": "mixed",
type: "multipolygon",
website: "http://ktahalle.be/",
_backend: "https://osm.org",
})
expect(data.geometry.type).eq("MultiPolygon")
expect(data).deep.eq(expected)
@ -240,7 +117,7 @@ function test(done: () => void){
osmConnection: {
Backend(): string {
return "https://osm.org"
}
},
},
filteredLayers: new UIEventSource<FilteredLayer[]>([
{
@ -248,31 +125,39 @@ function test(done: () => void){
layerDef: new LayerConfig({
id: "school",
source: {
osmTags: "amenity=school"
osmTags: "amenity=school",
},
mapRendering: null
mapRendering: null,
}),
isDisplayed: new UIEventSource<boolean>(true)
}
])
}
isDisplayed: new UIEventSource<boolean>(true),
},
]),
},
})
}
describe("OsmFeatureSource", () => {
it("downloading the full school should give a multipolygon", (done) => {
ScriptUtils.fixUtils()
let data = JSON.parse(readFileSync("./test/Logic/FeatureSource/osmdata.json", "utf8"))
Utils.injectJsonDownloadForTests("https://osm.org/api/0.6/map?bbox=4.24346923828125,50.732978448277514,4.2462158203125,50.73471682490244", data)
Utils.injectJsonDownloadForTests(
"https://osm.org/api/0.6/map?bbox=4.24346923828125,50.732978448277514,4.2462158203125,50.73471682490244",
data
)
test(done)
})
it("downloading the partial school polygon should give a multipolygon", (done) => {
ScriptUtils.fixUtils()
Utils.injectJsonDownloadForTests("https://www.openstreetmap.org/api/0.6/relation/5759328/full", JSON.parse(readFileSync("./test/data/relation_5759328.json","UTF-8")))
Utils.injectJsonDownloadForTests(
"https://www.openstreetmap.org/api/0.6/relation/5759328/full",
JSON.parse(readFileSync("./test/data/relation_5759328.json", "UTF-8"))
)
let data = JSON.parse(readFileSync("./test/Logic/FeatureSource/small_box.json", "utf8"))
Utils.injectJsonDownloadForTests("https://osm.org/api/0.6/map?bbox=4.24346923828125,50.732978448277514,4.2462158203125,50.73471682490244", data)
Utils.injectJsonDownloadForTests(
"https://osm.org/api/0.6/map?bbox=4.24346923828125,50.732978448277514,4.2462158203125,50.73471682490244",
data
)
test(done)
})
})
})

View file

@ -1,25 +1,23 @@
import {describe} from 'mocha'
import TileFreshnessCalculator from "../../../Logic/FeatureSource/TileFreshnessCalculator";
import {Tiles} from "../../../Models/TileRange";
import {expect} from "chai"
import { describe } from "mocha"
import TileFreshnessCalculator from "../../../Logic/FeatureSource/TileFreshnessCalculator"
import { Tiles } from "../../../Models/TileRange"
import { expect } from "chai"
describe("TileFreshnessCalculator", () => {
it("should get the freshness for loaded tiles", () => {
const calc = new TileFreshnessCalculator()
// 19/266407/175535
const date = new Date()
date.setTime(42)
calc.addTileLoad(Tiles.tile_index(19, 266406, 175534), date)
it("should get the freshness for loaded tiles",
() => {
const calc = new TileFreshnessCalculator();
// 19/266407/175535
const date = new Date()
date.setTime(42)
calc.addTileLoad(Tiles.tile_index(19, 266406, 175534), date)
expect(calc.freshnessFor(19, 266406, 175534).getTime()).eq(42)
expect(calc.freshnessFor(20, 266406 * 2, 175534 * 2 + 1).getTime()).eq(42)
expect(calc.freshnessFor(19, 266406, 175535)).undefined
expect(calc.freshnessFor(18, 266406 / 2, 175534 / 2)).undefined
calc.addTileLoad(Tiles.tile_index(19, 266406, 175534 + 1), date)
calc.addTileLoad(Tiles.tile_index(19, 266406 + 1, 175534), date)
calc.addTileLoad(Tiles.tile_index(19, 266406 + 1, 175534 + 1), date)
expect(calc.freshnessFor(18, 266406 / 2, 175534 / 2).getTime()).eq(42)
})
expect(calc.freshnessFor(19, 266406, 175534).getTime()).eq(42)
expect(calc.freshnessFor(20, 266406 * 2, 175534 * 2 + 1).getTime()).eq(42)
expect(calc.freshnessFor(19, 266406, 175535)).undefined
expect(calc.freshnessFor(18, 266406 / 2, 175534 / 2)).undefined
calc.addTileLoad(Tiles.tile_index(19, 266406, 175534 + 1), date)
calc.addTileLoad(Tiles.tile_index(19, 266406 + 1, 175534), date)
calc.addTileLoad(Tiles.tile_index(19, 266406 + 1, 175534 + 1), date)
expect(calc.freshnessFor(18, 266406 / 2, 175534 / 2).getTime()).eq(42)
})
})

View file

@ -1,174 +1,125 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import * as turf from "@turf/turf";
import {GeoOperations} from "../../Logic/GeoOperations";
import { describe } from "mocha"
import { expect } from "chai"
import * as turf from "@turf/turf"
import { GeoOperations } from "../../Logic/GeoOperations"
describe("GeoOperations", () => {
describe("calculateOverlap", () => {
it("should not give too much overlap (regression test)", () => {
const polyGrb = {
"type": "Feature",
"properties": {
"osm_id": "25189153",
"size_grb_building": "217.14",
type: "Feature",
properties: {
osm_id: "25189153",
size_grb_building: "217.14",
"addr:housenumber": "173",
"addr:street": "Kortrijksestraat",
"building": "house",
building: "house",
"source:geometry:entity": "Gbg",
"source:geometry:date": "2015/02/27",
"source:geometry:oidn": "1729460",
"source:geometry:uidn": "8713648",
"H_DTM_MIN": "17.28",
"H_DTM_GEM": "17.59",
"H_DSM_MAX": "29.04",
"H_DSM_P99": "28.63",
"HN_MAX": "11.45",
"HN_P99": "11.04",
"detection_method": "from existing OSM building source: house ,hits (3)",
"auto_building": "house",
"size_shared": "210.68",
"size_source_building": "212.63",
"id": "https://betadata.grbosm.site/grb?bbox=360935.6475626023,6592540.815539878,361088.52161917265,6592693.689596449/37",
"_lat": "50.83736194999996",
"_lon": "3.2432137000000116",
"_layer": "GRB",
"_length": "48.51529464293261",
H_DTM_MIN: "17.28",
H_DTM_GEM: "17.59",
H_DSM_MAX: "29.04",
H_DSM_P99: "28.63",
HN_MAX: "11.45",
HN_P99: "11.04",
detection_method: "from existing OSM building source: house ,hits (3)",
auto_building: "house",
size_shared: "210.68",
size_source_building: "212.63",
id: "https://betadata.grbosm.site/grb?bbox=360935.6475626023,6592540.815539878,361088.52161917265,6592693.689596449/37",
_lat: "50.83736194999996",
_lon: "3.2432137000000116",
_layer: "GRB",
_length: "48.51529464293261",
"_length:km": "0.0",
"_now:date": "2021-12-05",
"_now:datetime": "2021-12-05 21:51:40",
"_loaded:date": "2021-12-05",
"_loaded:datetime": "2021-12-05 21:51:40"
"_loaded:datetime": "2021-12-05 21:51:40",
},
"geometry": {
"type": "Polygon",
"coordinates": [
geometry: {
type: "Polygon",
coordinates: [
[
[
3.2431059999999974,
50.83730270000021
],
[
3.243174299999987,
50.83728850000007
],
[
3.2432116000000173,
50.83736910000003
],
[
3.2433214000000254,
50.83740350000011
],
[
3.24329779999996,
50.837435399999855
],
[
3.2431881000000504,
50.83740090000025
],
[
3.243152699999997,
50.83738980000017
],
[
3.2431059999999974,
50.83730270000021
]
]
]
[3.2431059999999974, 50.83730270000021],
[3.243174299999987, 50.83728850000007],
[3.2432116000000173, 50.83736910000003],
[3.2433214000000254, 50.83740350000011],
[3.24329779999996, 50.837435399999855],
[3.2431881000000504, 50.83740090000025],
[3.243152699999997, 50.83738980000017],
[3.2431059999999974, 50.83730270000021],
],
],
},
id: "https://betadata.grbosm.site/grb?bbox=360935.6475626023,6592540.815539878,361088.52161917265,6592693.689596449/37",
_lon: 3.2432137000000116,
_lat: 50.83736194999996,
bbox: {
maxLat: 50.837435399999855,
maxLon: 3.2433214000000254,
minLat: 50.83728850000007,
minLon: 3.2431059999999974,
},
"id": "https://betadata.grbosm.site/grb?bbox=360935.6475626023,6592540.815539878,361088.52161917265,6592693.689596449/37",
"_lon": 3.2432137000000116,
"_lat": 50.83736194999996,
"bbox": {
"maxLat": 50.837435399999855,
"maxLon": 3.2433214000000254,
"minLat": 50.83728850000007,
"minLon": 3.2431059999999974
}
}
const polyHouse = {
"type": "Feature",
"id": "way/594963177",
"properties": {
"timestamp": "2021-12-05T04:04:55Z",
"version": 3,
"changeset": 114571409,
"user": "Pieter Vander Vennet",
"uid": 3818858,
type: "Feature",
id: "way/594963177",
properties: {
timestamp: "2021-12-05T04:04:55Z",
version: 3,
changeset: 114571409,
user: "Pieter Vander Vennet",
uid: 3818858,
"addr:housenumber": "171",
"addr:street": "Kortrijksestraat",
"building": "house",
building: "house",
"source:geometry:date": "2018-10-22",
"source:geometry:ref": "Gbg/5096537",
"_last_edit:contributor": "Pieter Vander Vennet",
"_last_edit:contributor:uid": 3818858,
"_last_edit:changeset": 114571409,
"_last_edit:timestamp": "2021-12-05T04:04:55Z",
"_version_number": 3,
"id": "way/594963177",
"_backend": "https://www.openstreetmap.org",
"_lat": "50.83736395",
"_lon": "3.2430937",
"_layer": "OSM-buildings",
"_length": "43.561938680928506",
_version_number: 3,
id: "way/594963177",
_backend: "https://www.openstreetmap.org",
_lat: "50.83736395",
_lon: "3.2430937",
_layer: "OSM-buildings",
_length: "43.561938680928506",
"_length:km": "0.0",
"_now:date": "2021-12-05",
"_now:datetime": "2021-12-05 21:51:40",
"_loaded:date": "2021-12-05",
"_loaded:datetime": "2021-12-05 21:51:39",
"_surface": "93.32785810484549",
"_surface:ha": "0"
_surface: "93.32785810484549",
"_surface:ha": "0",
},
"geometry": {
"type": "Polygon",
"coordinates": [
geometry: {
type: "Polygon",
coordinates: [
[
[
3.2429993,
50.8373243
],
[
3.243106,
50.8373027
],
[
3.2431527,
50.8373898
],
[
3.2431881,
50.8374009
],
[
3.2431691,
50.8374252
],
[
3.2430936,
50.837401
],
[
3.243046,
50.8374112
],
[
3.2429993,
50.8373243
]
]
]
[3.2429993, 50.8373243],
[3.243106, 50.8373027],
[3.2431527, 50.8373898],
[3.2431881, 50.8374009],
[3.2431691, 50.8374252],
[3.2430936, 50.837401],
[3.243046, 50.8374112],
[3.2429993, 50.8373243],
],
],
},
_lon: 3.2430937,
_lat: 50.83736395,
bbox: {
maxLat: 50.8374252,
maxLon: 3.2431881,
minLat: 50.8373027,
minLon: 3.2429993,
},
"_lon": 3.2430937,
"_lat": 50.83736395,
"bbox": {
"maxLat": 50.8374252,
"maxLon": 3.2431881,
"minLat": 50.8373027,
"minLon": 3.2429993
}
}
const p0 = turf.polygon(polyGrb.geometry.coordinates)
@ -176,11 +127,10 @@ describe("GeoOperations", () => {
const p1 = turf.polygon(polyHouse.geometry.coordinates)
expect(p1).not.null
const overlaps = GeoOperations.calculateOverlap(polyGrb, [polyHouse])
expect(overlaps).empty
const overlapsRev = GeoOperations.calculateOverlap(polyHouse, [polyGrb])
expect(overlapsRev).empty
})
})
})
})

View file

@ -1,77 +1,102 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import AllImageProviders from "../../../Logic/ImageProviders/AllImageProviders";
import {UIEventSource} from "../../../Logic/UIEventSource";
import {Utils} from "../../../Utils";
import { describe } from "mocha"
import { expect } from "chai"
import AllImageProviders from "../../../Logic/ImageProviders/AllImageProviders"
import { UIEventSource } from "../../../Logic/UIEventSource"
import { Utils } from "../../../Utils"
describe("ImageProviders", () => {
it("should work on a variaty of inputs", () => {
let i = 0
function expects(url, tags, providerName = undefined) {
tags.id = "test/" + i
i++
AllImageProviders.LoadImagesFor(new UIEventSource(tags)).addCallbackD(images => {
console.log("ImageProvider test", tags.id, "for", tags)
const img = images[0]
if (img === undefined) {
throw "No image found"
}
expect(img.url).deep.equal(url)
if (providerName) {
expect(providerName).deep.equal(img.provider.constructor.name)
}
console.log("OK")
})
}
const muntpoort_expected = "https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABr%C3%BCgge-Muntpoort_6-29510-58192.jpg?width=500&height=400"
expects(
muntpoort_expected,
{
"wikimedia_commons": "File:Brügge-Muntpoort_6-29510-58192.jpg"
}, "WikimediaImageProvider")
expects(muntpoort_expected,
{
"wikimedia_commons": "https://upload.wikimedia.org/wikipedia/commons/c/cd/Br%C3%BCgge-Muntpoort_6-29510-58192.jpg"
}, "WikimediaImageProvider")
expects(muntpoort_expected, {
"image": "https://upload.wikimedia.org/wikipedia/commons/c/cd/Br%C3%BCgge-Muntpoort_6-29510-58192.jpg"
}, "WikimediaImageProvider")
expects("https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABelgium-5955_-_Simon_Stevin_(13746657193).jpg?width=500&height=400", {
"image": "File:Belgium-5955_-_Simon_Stevin_(13746657193).jpg"
}, "WikimediaImageProvider")
expects("https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABelgium-5955_-_Simon_Stevin_(13746657193).jpg?width=500&height=400", {
"wikimedia_commons": "File:Belgium-5955_-_Simon_Stevin_(13746657193).jpg"
}, "WikimediaImageProvider")
expects("https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABrugge_Leeuwstraat_zonder_nummer_Leeuwbrug_-_119334_-_onroerenderfgoed.jpg?width=500&height=400", {
image: "File:Brugge_Leeuwstraat_zonder_nummer_Leeuwbrug_-_119334_-_onroerenderfgoed.jpg"
}, "WikimediaImageProvider")
expects("https://commons.wikimedia.org/wiki/Special:FilePath/File%3APapageno_Jef_Claerhout.jpg?width=500&height=400", {
"wikimedia_commons": "File:Papageno_Jef_Claerhout.jpg"
}, "WikimediaImageProvider")
Utils.injectJsonDownloadForTests(
"https://graph.mapillary.com/196804715753265?fields=thumb_1024_url&&access_token=MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85",
{
"thumb_1024_url": "https://scontent-bru2-1.xx.fbcdn.net/m1/v/t6/An8HQ3DrfU76tWMC602spvM_e_rqOHyiUcYUTetXM7K52DDBEY5J4FWg4WKQqVUlMsWJn4nLXk0pxlBLx31146FqZ2Kg65z7lJUfR6wpW6WPSR5_y7RKdv4YEuzPjwIN0lagBnQONV3UjmXnEGpMouU?stp=s1024x768&ccb=10-5&oh=d460b401c505714ee1cb8bd6baf8ae5d&oe=61731FC3&_nc_sid=122ab1",
"id": "196804715753265"
it("should work on a variaty of inputs", () => {
let i = 0
function expects(url, tags, providerName = undefined) {
tags.id = "test/" + i
i++
AllImageProviders.LoadImagesFor(new UIEventSource(tags)).addCallbackD((images) => {
console.log("ImageProvider test", tags.id, "for", tags)
const img = images[0]
if (img === undefined) {
throw "No image found"
}
)
expects("https://scontent-bru2-1.xx.fbcdn.net/m1/v/t6/An8HQ3DrfU76tWMC602spvM_e_rqOHyiUcYUTetXM7K52DDBEY5J4FWg4WKQqVUlMsWJn4nLXk0pxlBLx31146FqZ2Kg65z7lJUfR6wpW6WPSR5_y7RKdv4YEuzPjwIN0lagBnQONV3UjmXnEGpMouU?stp=s1024x768&ccb=10-5&oh=d460b401c505714ee1cb8bd6baf8ae5d&oe=61731FC3&_nc_sid=122ab1", {
"mapillary": "https://www.mapillary.com/app/?pKey=196804715753265"
expect(img.url).deep.equal(url)
if (providerName) {
expect(providerName).deep.equal(img.provider.constructor.name)
}
console.log("OK")
})
}
const muntpoort_expected =
"https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABr%C3%BCgge-Muntpoort_6-29510-58192.jpg?width=500&height=400"
expects(
muntpoort_expected,
{
wikimedia_commons: "File:Brügge-Muntpoort_6-29510-58192.jpg",
},
"WikimediaImageProvider"
)
})
})
expects(
muntpoort_expected,
{
wikimedia_commons:
"https://upload.wikimedia.org/wikipedia/commons/c/cd/Br%C3%BCgge-Muntpoort_6-29510-58192.jpg",
},
"WikimediaImageProvider"
)
expects(
muntpoort_expected,
{
image: "https://upload.wikimedia.org/wikipedia/commons/c/cd/Br%C3%BCgge-Muntpoort_6-29510-58192.jpg",
},
"WikimediaImageProvider"
)
expects(
"https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABelgium-5955_-_Simon_Stevin_(13746657193).jpg?width=500&height=400",
{
image: "File:Belgium-5955_-_Simon_Stevin_(13746657193).jpg",
},
"WikimediaImageProvider"
)
expects(
"https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABelgium-5955_-_Simon_Stevin_(13746657193).jpg?width=500&height=400",
{
wikimedia_commons: "File:Belgium-5955_-_Simon_Stevin_(13746657193).jpg",
},
"WikimediaImageProvider"
)
expects(
"https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABrugge_Leeuwstraat_zonder_nummer_Leeuwbrug_-_119334_-_onroerenderfgoed.jpg?width=500&height=400",
{
image: "File:Brugge_Leeuwstraat_zonder_nummer_Leeuwbrug_-_119334_-_onroerenderfgoed.jpg",
},
"WikimediaImageProvider"
)
expects(
"https://commons.wikimedia.org/wiki/Special:FilePath/File%3APapageno_Jef_Claerhout.jpg?width=500&height=400",
{
wikimedia_commons: "File:Papageno_Jef_Claerhout.jpg",
},
"WikimediaImageProvider"
)
Utils.injectJsonDownloadForTests(
"https://graph.mapillary.com/196804715753265?fields=thumb_1024_url&&access_token=MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85",
{
thumb_1024_url:
"https://scontent-bru2-1.xx.fbcdn.net/m1/v/t6/An8HQ3DrfU76tWMC602spvM_e_rqOHyiUcYUTetXM7K52DDBEY5J4FWg4WKQqVUlMsWJn4nLXk0pxlBLx31146FqZ2Kg65z7lJUfR6wpW6WPSR5_y7RKdv4YEuzPjwIN0lagBnQONV3UjmXnEGpMouU?stp=s1024x768&ccb=10-5&oh=d460b401c505714ee1cb8bd6baf8ae5d&oe=61731FC3&_nc_sid=122ab1",
id: "196804715753265",
}
)
expects(
"https://scontent-bru2-1.xx.fbcdn.net/m1/v/t6/An8HQ3DrfU76tWMC602spvM_e_rqOHyiUcYUTetXM7K52DDBEY5J4FWg4WKQqVUlMsWJn4nLXk0pxlBLx31146FqZ2Kg65z7lJUfR6wpW6WPSR5_y7RKdv4YEuzPjwIN0lagBnQONV3UjmXnEGpMouU?stp=s1024x768&ccb=10-5&oh=d460b401c505714ee1cb8bd6baf8ae5d&oe=61731FC3&_nc_sid=122ab1",
{
mapillary: "https://www.mapillary.com/app/?pKey=196804715753265",
}
)
})
})

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
import {expect} from 'chai'
import {ChangeDescription} from "../../../Logic/Osm/Actions/ChangeDescription";
import {Changes} from "../../../Logic/Osm/Changes";
import { expect } from "chai"
import { ChangeDescription } from "../../../Logic/Osm/Actions/ChangeDescription"
import { Changes } from "../../../Logic/Osm/Changes"
it("Generate preXML from changeDescriptions", () => {
const changeDescrs: ChangeDescription[] = [
@ -9,29 +9,26 @@ it("Generate preXML from changeDescriptions", () => {
id: -1,
changes: {
lat: 42,
lon: -8
lon: -8,
},
tags: [{k: "someKey", v: "someValue"}],
tags: [{ k: "someKey", v: "someValue" }],
meta: {
changeType: "create",
theme: "test"
}
theme: "test",
},
},
{
type: "node",
id: -1,
tags: [{k: 'foo', v: 'bar'}],
tags: [{ k: "foo", v: "bar" }],
meta: {
changeType: "answer",
theme: "test"
}
}
theme: "test",
},
},
]
const c = new Changes()
const descr = c.CreateChangesetObjects(
changeDescrs,
[]
)
const descr = c.CreateChangesetObjects(changeDescrs, [])
expect(descr.modifiedObjects).length(0)
expect(descr.deletedObjects).length(0)
expect(descr.newObjects).length(1)
@ -39,4 +36,4 @@ it("Generate preXML from changeDescriptions", () => {
const ch = descr.newObjects[0]
expect(ch.tags["foo"]).eq("bar")
expect(ch.tags["someKey"]).eq("someValue")
})
})

View file

@ -1,62 +1,66 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {Utils} from "../../../Utils";
import {ChangesetHandler, ChangesetTag} from "../../../Logic/Osm/ChangesetHandler";
import {UIEventSource} from "../../../Logic/UIEventSource";
import {OsmConnection} from "../../../Logic/Osm/OsmConnection";
import {ElementStorage} from "../../../Logic/ElementStorage";
import {Changes} from "../../../Logic/Osm/Changes";
import { describe } from "mocha"
import { expect } from "chai"
import { Utils } from "../../../Utils"
import { ChangesetHandler, ChangesetTag } from "../../../Logic/Osm/ChangesetHandler"
import { UIEventSource } from "../../../Logic/UIEventSource"
import { OsmConnection } from "../../../Logic/Osm/OsmConnection"
import { ElementStorage } from "../../../Logic/ElementStorage"
import { Changes } from "../../../Logic/Osm/Changes"
describe("ChangesetHanlder", () => {
describe("RewriteTagsOf", () => {
it("should insert new tags", () => {
const changesetHandler = new ChangesetHandler(new UIEventSource<boolean>(true),
const changesetHandler = new ChangesetHandler(
new UIEventSource<boolean>(true),
new OsmConnection({}),
new ElementStorage(),
new Changes(),
new UIEventSource(undefined)
);
)
const oldChangesetMeta = {
"type": "changeset",
"id": 118443748,
"created_at": "2022-03-13T19:52:10Z",
"closed_at": "2022-03-13T20:54:35Z",
"open": false,
"user": "Pieter Vander Vennet",
"uid": 3818858,
"minlat": 51.0361902,
"minlon": 3.7092939,
"maxlat": 51.0364194,
"maxlon": 3.7099520,
"comments_count": 0,
"changes_count": 3,
"tags": {
"answer": "5",
"comment": "Adding data with #MapComplete for theme #toerisme_vlaanderen",
"created_by": "MapComplete 0.16.6",
"host": "https://mapcomplete.osm.be/toerisme_vlaanderen.html",
"imagery": "osm",
"locale": "nl",
"source": "survey",
type: "changeset",
id: 118443748,
created_at: "2022-03-13T19:52:10Z",
closed_at: "2022-03-13T20:54:35Z",
open: false,
user: "Pieter Vander Vennet",
uid: 3818858,
minlat: 51.0361902,
minlon: 3.7092939,
maxlat: 51.0364194,
maxlon: 3.709952,
comments_count: 0,
changes_count: 3,
tags: {
answer: "5",
comment: "Adding data with #MapComplete for theme #toerisme_vlaanderen",
created_by: "MapComplete 0.16.6",
host: "https://mapcomplete.osm.be/toerisme_vlaanderen.html",
imagery: "osm",
locale: "nl",
source: "survey",
"source:node/-1": "note/1234",
"theme": "toerisme_vlaanderen",
}
theme: "toerisme_vlaanderen",
},
}
const rewritten = changesetHandler.RewriteTagsOf(
[{
key: "newTag",
value: "newValue",
aggregate: false
}],
[
{
key: "newTag",
value: "newValue",
aggregate: false,
},
],
new Map<string, string>(),
oldChangesetMeta)
oldChangesetMeta
)
const d = Utils.asDict(rewritten)
expect(d.size).deep.equal(10)
expect(d.get("answer")).deep.equal("5")
expect(d.get("comment")).deep.equal("Adding data with #MapComplete for theme #toerisme_vlaanderen")
expect(d.get("comment")).deep.equal(
"Adding data with #MapComplete for theme #toerisme_vlaanderen"
)
expect(d.get("created_by")).deep.equal("MapComplete 0.16.6")
expect(d.get("host")).deep.equal("https://mapcomplete.osm.be/toerisme_vlaanderen.html")
expect(d.get("imagery")).deep.equal("osm")
@ -64,54 +68,59 @@ describe("ChangesetHanlder", () => {
expect(d.get("source:node/-1")).deep.equal("note/1234")
expect(d.get("theme")).deep.equal("toerisme_vlaanderen")
expect(d.get("newTag")).deep.equal("newValue")
})
it("should aggregate numeric tags", () => {
const changesetHandler = new ChangesetHandler(new UIEventSource<boolean>(true),
const changesetHandler = new ChangesetHandler(
new UIEventSource<boolean>(true),
new OsmConnection({}),
new ElementStorage(),
new Changes(),
new UIEventSource(undefined)
);
)
const oldChangesetMeta = {
"type": "changeset",
"id": 118443748,
"created_at": "2022-03-13T19:52:10Z",
"closed_at": "2022-03-13T20:54:35Z",
"open": false,
"user": "Pieter Vander Vennet",
"uid": 3818858,
"minlat": 51.0361902,
"minlon": 3.7092939,
"maxlat": 51.0364194,
"maxlon": 3.7099520,
"comments_count": 0,
"changes_count": 3,
"tags": {
"answer": "5",
"comment": "Adding data with #MapComplete for theme #toerisme_vlaanderen",
"created_by": "MapComplete 0.16.6",
"host": "https://mapcomplete.osm.be/toerisme_vlaanderen.html",
"imagery": "osm",
"locale": "nl",
"source": "survey",
type: "changeset",
id: 118443748,
created_at: "2022-03-13T19:52:10Z",
closed_at: "2022-03-13T20:54:35Z",
open: false,
user: "Pieter Vander Vennet",
uid: 3818858,
minlat: 51.0361902,
minlon: 3.7092939,
maxlat: 51.0364194,
maxlon: 3.709952,
comments_count: 0,
changes_count: 3,
tags: {
answer: "5",
comment: "Adding data with #MapComplete for theme #toerisme_vlaanderen",
created_by: "MapComplete 0.16.6",
host: "https://mapcomplete.osm.be/toerisme_vlaanderen.html",
imagery: "osm",
locale: "nl",
source: "survey",
"source:node/-1": "note/1234",
"theme": "toerisme_vlaanderen",
}
theme: "toerisme_vlaanderen",
},
}
const rewritten = changesetHandler.RewriteTagsOf(
[{
key: "answer",
value: "37",
aggregate: true
}],
[
{
key: "answer",
value: "37",
aggregate: true,
},
],
new Map<string, string>(),
oldChangesetMeta)
oldChangesetMeta
)
const d = Utils.asDict(rewritten)
expect(d.size).deep.equal(9)
expect(d.get("answer")).deep.equal("42")
expect(d.get("comment")).deep.equal("Adding data with #MapComplete for theme #toerisme_vlaanderen")
expect(d.get("comment")).deep.equal(
"Adding data with #MapComplete for theme #toerisme_vlaanderen"
)
expect(d.get("created_by")).deep.equal("MapComplete 0.16.6")
expect(d.get("host")).deep.equal("https://mapcomplete.osm.be/toerisme_vlaanderen.html")
expect(d.get("imagery")).deep.equal("osm")
@ -120,47 +129,51 @@ describe("ChangesetHanlder", () => {
expect(d.get("theme")).deep.equal("toerisme_vlaanderen")
})
it("should rewrite special reasons with the correct ID", () => {
const changesetHandler = new ChangesetHandler(new UIEventSource<boolean>(true),
const changesetHandler = new ChangesetHandler(
new UIEventSource<boolean>(true),
new OsmConnection({}),
new ElementStorage(),
new Changes(),
new UIEventSource(undefined)
);
)
const oldChangesetMeta = {
"type": "changeset",
"id": 118443748,
"created_at": "2022-03-13T19:52:10Z",
"closed_at": "2022-03-13T20:54:35Z",
"open": false,
"user": "Pieter Vander Vennet",
"uid": 3818858,
"minlat": 51.0361902,
"minlon": 3.7092939,
"maxlat": 51.0364194,
"maxlon": 3.7099520,
"comments_count": 0,
"changes_count": 3,
"tags": {
"answer": "5",
"comment": "Adding data with #MapComplete for theme #toerisme_vlaanderen",
"created_by": "MapComplete 0.16.6",
"host": "https://mapcomplete.osm.be/toerisme_vlaanderen.html",
"imagery": "osm",
"locale": "nl",
"source": "survey",
type: "changeset",
id: 118443748,
created_at: "2022-03-13T19:52:10Z",
closed_at: "2022-03-13T20:54:35Z",
open: false,
user: "Pieter Vander Vennet",
uid: 3818858,
minlat: 51.0361902,
minlon: 3.7092939,
maxlat: 51.0364194,
maxlon: 3.709952,
comments_count: 0,
changes_count: 3,
tags: {
answer: "5",
comment: "Adding data with #MapComplete for theme #toerisme_vlaanderen",
created_by: "MapComplete 0.16.6",
host: "https://mapcomplete.osm.be/toerisme_vlaanderen.html",
imagery: "osm",
locale: "nl",
source: "survey",
"source:node/-1": "note/1234",
"theme": "toerisme_vlaanderen",
}
theme: "toerisme_vlaanderen",
},
}
const rewritten = changesetHandler.RewriteTagsOf(
[],
new Map<string, string>([["node/-1", "node/42"]]),
oldChangesetMeta)
oldChangesetMeta
)
const d = Utils.asDict(rewritten)
expect(d.size).deep.equal(9)
expect(d.get("answer")).deep.equal("5")
expect(d.get("comment")).deep.equal("Adding data with #MapComplete for theme #toerisme_vlaanderen")
expect(d.get("comment")).deep.equal(
"Adding data with #MapComplete for theme #toerisme_vlaanderen"
)
expect(d.get("created_by")).deep.equal("MapComplete 0.16.6")
expect(d.get("host")).deep.equal("https://mapcomplete.osm.be/toerisme_vlaanderen.html")
expect(d.get("imagery")).deep.equal("osm")
@ -169,21 +182,24 @@ describe("ChangesetHanlder", () => {
expect(d.get("theme")).deep.equal("toerisme_vlaanderen")
})
})
describe("rewriteMetaTags" , () => {
describe("rewriteMetaTags", () => {
it("should rewrite special reasons with the correct ID", () => {
const extraMetaTags : ChangesetTag[] = [
const extraMetaTags: ChangesetTag[] = [
{
key: "created_by",
value:"mapcomplete"
value: "mapcomplete",
},
{
key: "source:node/-1",
value:"note/1234"
}
value: "note/1234",
},
]
const changes = new Map<string, string>([["node/-1","node/42"]])
const hasSpecialMotivationChanges = ChangesetHandler.rewriteMetaTags(extraMetaTags, changes)
const changes = new Map<string, string>([["node/-1", "node/42"]])
const hasSpecialMotivationChanges = ChangesetHandler.rewriteMetaTags(
extraMetaTags,
changes
)
expect(hasSpecialMotivationChanges, "Special rewrite did not trigger").true
// Rewritten inline by rewriteMetaTags
expect(extraMetaTags[1].key).deep.equal("source:node/42")
@ -191,5 +207,5 @@ describe("ChangesetHanlder", () => {
expect(extraMetaTags[0].key).deep.equal("created_by")
expect(extraMetaTags[0].value).deep.equal("mapcomplete")
})
})
})
})

View file

@ -1,93 +1,99 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {OsmObject} from "../../../Logic/Osm/OsmObject";
import {Utils} from "../../../Utils";
import ScriptUtils from "../../../scripts/ScriptUtils";
import {readFileSync} from "fs";
import { describe } from "mocha"
import { expect } from "chai"
import { OsmObject } from "../../../Logic/Osm/OsmObject"
import { Utils } from "../../../Utils"
import ScriptUtils from "../../../scripts/ScriptUtils"
import { readFileSync } from "fs"
describe("OsmObject", () => {
describe("download referencing ways", () => {
Utils.injectJsonDownloadForTests(
"https://www.openstreetmap.org/api/0.6/node/1124134958/ways", {
"version": "0.6",
"generator": "CGImap 0.8.6 (49805 spike-06.openstreetmap.org)",
"copyright": "OpenStreetMap and contributors",
"attribution": "http://www.openstreetmap.org/copyright",
"license": "http://opendatacommons.org/licenses/odbl/1-0/",
"elements": [{
"type": "way",
"id": 97038428,
"timestamp": "2019-06-19T12:26:24Z",
"version": 6,
"changeset": 71399984,
"user": "Pieter Vander Vennet",
"uid": 3818858,
"nodes": [1124134958, 323729212, 323729351, 2542460408, 187073405],
"tags": {
"highway": "residential",
"name": "Brugs-Kerkhofstraat",
"sett:pattern": "arc",
"surface": "sett"
}
}, {
"type": "way",
"id": 97038434,
"timestamp": "2019-06-19T12:26:24Z",
"version": 5,
"changeset": 71399984,
"user": "Pieter Vander Vennet",
"uid": 3818858,
"nodes": [1124134958, 1124135024, 187058607],
"tags": {
"bicycle": "use_sidepath",
"highway": "residential",
"name": "Kerkhofblommenstraat",
"sett:pattern": "arc",
"surface": "sett"
}
}, {
"type": "way",
"id": 97038435,
"timestamp": "2017-12-21T21:41:08Z",
"version": 4,
"changeset": 54826837,
"user": "Jakka",
"uid": 2403313,
"nodes": [1124134958, 2576628889, 1124135035, 5298371485, 5298371495],
"tags": {"bicycle": "use_sidepath", "highway": "residential", "name": "Kerkhofblommenstraat"}
}, {
"type": "way",
"id": 251446313,
"timestamp": "2019-01-07T19:22:47Z",
"version": 4,
"changeset": 66106872,
"user": "M!dgard",
"uid": 763799,
"nodes": [1124134958, 5243143198, 4555715455],
"tags": {"foot": "yes", "highway": "service"}
}]
})
"https://www.openstreetmap.org/api/0.6/node/1124134958/ways",
{
version: "0.6",
generator: "CGImap 0.8.6 (49805 spike-06.openstreetmap.org)",
copyright: "OpenStreetMap and contributors",
attribution: "http://www.openstreetmap.org/copyright",
license: "http://opendatacommons.org/licenses/odbl/1-0/",
elements: [
{
type: "way",
id: 97038428,
timestamp: "2019-06-19T12:26:24Z",
version: 6,
changeset: 71399984,
user: "Pieter Vander Vennet",
uid: 3818858,
nodes: [1124134958, 323729212, 323729351, 2542460408, 187073405],
tags: {
highway: "residential",
name: "Brugs-Kerkhofstraat",
"sett:pattern": "arc",
surface: "sett",
},
},
{
type: "way",
id: 97038434,
timestamp: "2019-06-19T12:26:24Z",
version: 5,
changeset: 71399984,
user: "Pieter Vander Vennet",
uid: 3818858,
nodes: [1124134958, 1124135024, 187058607],
tags: {
bicycle: "use_sidepath",
highway: "residential",
name: "Kerkhofblommenstraat",
"sett:pattern": "arc",
surface: "sett",
},
},
{
type: "way",
id: 97038435,
timestamp: "2017-12-21T21:41:08Z",
version: 4,
changeset: 54826837,
user: "Jakka",
uid: 2403313,
nodes: [1124134958, 2576628889, 1124135035, 5298371485, 5298371495],
tags: {
bicycle: "use_sidepath",
highway: "residential",
name: "Kerkhofblommenstraat",
},
},
{
type: "way",
id: 251446313,
timestamp: "2019-01-07T19:22:47Z",
version: 4,
changeset: 66106872,
user: "M!dgard",
uid: 763799,
nodes: [1124134958, 5243143198, 4555715455],
tags: { foot: "yes", highway: "service" },
},
],
}
)
it("should download referencing ways", async () => {
const ways = await OsmObject.DownloadReferencingWays("node/1124134958")
expect(ways).not.undefined
expect(ways).length(4)
})
it("should download referencing ways",
async () => {
const ways = await OsmObject.DownloadReferencingWays("node/1124134958")
expect(ways).not.undefined
expect(ways).length(4)
})
it("should download full OSM-relations", async () => {
ScriptUtils.fixUtils()
Utils.injectJsonDownloadForTests("https://www.openstreetmap.org/api/0.6/relation/5759328/full", JSON.parse(readFileSync("./test/data/relation_5759328.json","UTF-8")))
const r = await OsmObject.DownloadObjectAsync("relation/5759328").then(x => x)
const geojson = r.asGeoJson();
Utils.injectJsonDownloadForTests(
"https://www.openstreetmap.org/api/0.6/relation/5759328/full",
JSON.parse(readFileSync("./test/data/relation_5759328.json", "UTF-8"))
)
const r = await OsmObject.DownloadObjectAsync("relation/5759328").then((x) => x)
const geojson = r.asGeoJson()
expect(geojson.geometry.type).eq("MultiPolygon")
})
})
})

View file

@ -1,11 +1,9 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {TagUtils} from "../../../Logic/Tags/TagUtils";
import {Tag} from "../../../Logic/Tags/Tag";
import { describe } from "mocha"
import { expect } from "chai"
import { TagUtils } from "../../../Logic/Tags/TagUtils"
import { Tag } from "../../../Logic/Tags/Tag"
describe("Lazy object properties", () => {
it("should be matche by a normal tag", () => {
const properties = {}
const key = "_key"
@ -15,26 +13,24 @@ describe("Lazy object properties", () => {
delete properties[key]
properties[key] = "yes"
return "yes"
}
},
})
const filter = new Tag("_key", "yes")
expect(filter.matchesProperties(properties)).true
})
it("should be matched by a RegexTag", () => {
const properties = {}
const key = "_key"
Object.defineProperty(properties, key, {
configurable: true,
get: function () {
delete properties[key]
properties[key] = "yes"
return "yes"
}
})
const filter = TagUtils.Tag("_key~*")
expect(filter.matchesProperties(properties)).true;
it("should be matched by a RegexTag", () => {
const properties = {}
const key = "_key"
Object.defineProperty(properties, key, {
configurable: true,
get: function () {
delete properties[key]
properties[key] = "yes"
return "yes"
},
})
const filter = TagUtils.Tag("_key~*")
expect(filter.matchesProperties(properties)).true
})
})

View file

@ -1,129 +1,91 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {TagsFilter} from "../../../Logic/Tags/TagsFilter";
import {And} from "../../../Logic/Tags/And";
import {Tag} from "../../../Logic/Tags/Tag";
import {TagUtils} from "../../../Logic/Tags/TagUtils";
import {Or} from "../../../Logic/Tags/Or";
import {RegexTag} from "../../../Logic/Tags/RegexTag";
import { describe } from "mocha"
import { expect } from "chai"
import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
import { And } from "../../../Logic/Tags/And"
import { Tag } from "../../../Logic/Tags/Tag"
import { TagUtils } from "../../../Logic/Tags/TagUtils"
import { Or } from "../../../Logic/Tags/Or"
import { RegexTag } from "../../../Logic/Tags/RegexTag"
describe("Tag optimalization", () => {
describe("And", () => {
it("with condition and nested and should be flattened", () => {
const t = new And(
[
new And([
new Tag("x", "y")
]),
new Tag("a", "b")
]
)
const t = new And([new And([new Tag("x", "y")]), new Tag("a", "b")])
const opt = <TagsFilter>t.optimize()
expect(TagUtils.toString(opt)).eq(`a=b&x=y`)
})
it("should be 'true' if no conditions are given", () => {
const t = new And(
[]
)
const t = new And([])
const opt = t.optimize()
expect(opt).eq(true)
})
it("should return false on conflicting tags", () => {
const t = new And([new Tag("key","a"), new Tag("key","b")])
const t = new And([new Tag("key", "a"), new Tag("key", "b")])
const opt = t.optimize()
expect(opt).eq(false)
})
it("with nested ors and common property should be extracted", () => {
// foo&bar & (x=y | a=b) & (x=y | c=d) & foo=bar is equivalent too foo=bar & ((x=y) | (a=b & c=d))
const t = new And([
new Tag("foo", "bar"),
new Or([
new Tag("x", "y"),
new Tag("a", "b")
]),
new Or([
new Tag("x", "y"),
new Tag("c", "d")
])
new Or([new Tag("x", "y"), new Tag("a", "b")]),
new Or([new Tag("x", "y"), new Tag("c", "d")]),
])
const opt = <TagsFilter>t.optimize()
expect(TagUtils.toString(opt)).eq("foo=bar& (x=y| (a=b&c=d) )")
})
it("with nested ors and common regextag should be extracted", () => {
// foo&bar & (x=y | a=b) & (x=y | c=d) & foo=bar is equivalent too foo=bar & ((x=y) | (a=b & c=d))
const t = new And([
new Tag("foo", "bar"),
new Or([
new RegexTag("x", "y"),
new RegexTag("a", "b")
]),
new Or([
new RegexTag("x", "y"),
new RegexTag("c", "d")
])
new Or([new RegexTag("x", "y"), new RegexTag("a", "b")]),
new Or([new RegexTag("x", "y"), new RegexTag("c", "d")]),
])
const opt = <TagsFilter>t.optimize()
expect(TagUtils.toString(opt)).eq("foo=bar& ( (a=b&c=d) |x=y)")
})
it("with nested ors and inverted regextags should _not_ be extracted", () => {
// foo&bar & (x=y | a=b) & (x=y | c=d) & foo=bar is equivalent too foo=bar & ((x=y) | (a=b & c=d))
const t = new And([
new Tag("foo", "bar"),
new Or([
new RegexTag("x", "y"),
new RegexTag("a", "b")
]),
new Or([
new RegexTag("x", "y", true),
new RegexTag("c", "d")
])
new Or([new RegexTag("x", "y"), new RegexTag("a", "b")]),
new Or([new RegexTag("x", "y", true), new RegexTag("c", "d")]),
])
const opt = <TagsFilter>t.optimize()
expect(TagUtils.toString(opt)).eq("foo=bar& (a=b|x=y) & (c=d|x!=y)")
})
it("should move regextag to the end", () => {
const t = new And([
new RegexTag("x", "y"),
new Tag("a", "b")
])
const t = new And([new RegexTag("x", "y"), new Tag("a", "b")])
const opt = <TagsFilter>t.optimize()
expect(TagUtils.toString(opt)).eq("a=b&x=y")
})
it("should sort tags by their popularity (least popular first)", () => {
const t = new And([
new Tag("bicycle", "yes"),
new Tag("amenity", "binoculars")
])
const t = new And([new Tag("bicycle", "yes"), new Tag("amenity", "binoculars")])
const opt = <TagsFilter>t.optimize()
expect(TagUtils.toString(opt)).eq("amenity=binoculars&bicycle=yes")
})
it("should optimize nested ORs", () => {
const filter = TagUtils.Tag({
or: [
"X=Y", "FOO=BAR",
"X=Y",
"FOO=BAR",
{
"and": [
and: [
{
"or": ["X=Y", "FOO=BAR"]
or: ["X=Y", "FOO=BAR"],
},
"bicycle=yes"
]
}
]
"bicycle=yes",
],
},
],
})
// (X=Y | FOO=BAR | (bicycle=yes & (X=Y | FOO=BAR)) )
// This is equivalent to (X=Y | FOO=BAR)
@ -135,56 +97,60 @@ describe("Tag optimalization", () => {
const filter = TagUtils.Tag({
or: [
{
"and": [
and: [
{
"or": ["amenity=charging_station", "disused:amenity=charging_station", "planned:amenity=charging_station", "construction:amenity=charging_station"]
or: [
"amenity=charging_station",
"disused:amenity=charging_station",
"planned:amenity=charging_station",
"construction:amenity=charging_station",
],
},
"bicycle=yes"
]
"bicycle=yes",
],
},
{
"and": [
and: [
{
"or": ["amenity=charging_station", "disused:amenity=charging_station", "planned:amenity=charging_station", "construction:amenity=charging_station"]
or: [
"amenity=charging_station",
"disused:amenity=charging_station",
"planned:amenity=charging_station",
"construction:amenity=charging_station",
],
},
]
],
},
"amenity=toilets",
"amenity=bench",
"leisure=picnic_table",
{
"and": [
"tower:type=observation"
]
and: ["tower:type=observation"],
},
{
"and": [
"amenity=bicycle_repair_station"
]
and: ["amenity=bicycle_repair_station"],
},
{
"and": [
and: [
{
"or": [
or: [
"amenity=bicycle_rental",
"bicycle_rental~*",
"service:bicycle:rental=yes",
"rental~.*bicycle.*"
]
"rental~.*bicycle.*",
],
},
"bicycle_rental!=docking_station"
]
"bicycle_rental!=docking_station",
],
},
{
"and": [
"leisure=playground",
"playground!=forest"
]
}
]
});
and: ["leisure=playground", "playground!=forest"],
},
],
})
const opt = <TagsFilter>filter.optimize()
const expected = ["amenity=charging_station",
const expected = [
"amenity=charging_station",
"amenity=toilets",
"amenity=bench",
"amenity=bicycle_repair_station",
@ -194,11 +160,10 @@ describe("Tag optimalization", () => {
"planned:amenity=charging_station",
"tower:type=observation",
"(amenity=bicycle_rental|service:bicycle:rental=yes|bicycle_rental~^..*$|rental~^.*bicycle.*$) &bicycle_rental!=docking_station",
"leisure=playground&playground!=forest"]
"leisure=playground&playground!=forest",
]
expect((<Or>opt).or.map(f => TagUtils.toString(f))).deep.eq(
expected
)
expect((<Or>opt).or.map((f) => TagUtils.toString(f))).deep.eq(expected)
})
it("should detect conflicting tags", () => {
@ -210,79 +175,54 @@ describe("Tag optimalization", () => {
const q = new And([new Tag("key", "value"), new RegexTag("key", /value/, true)])
expect(q.optimize()).eq(false)
})
})
describe("Or", () => {
it("with nested And which has a common property should be dropped", () => {
const t = new Or([
new Tag("foo", "bar"),
new And([
new Tag("foo", "bar"),
new Tag("x", "y"),
])
new And([new Tag("foo", "bar"), new Tag("x", "y")]),
])
const opt = <TagsFilter>t.optimize()
expect(TagUtils.toString(opt)).eq("foo=bar")
})
it("should flatten nested ors", () => {
const t = new Or([
new Or([
new Tag("x", "y")
])
]).optimize()
const t = new Or([new Or([new Tag("x", "y")])]).optimize()
expect(t).deep.eq(new Tag("x", "y"))
})
it("should flatten nested ors", () => {
const t = new Or([
new Tag("a", "b"),
new Or([
new Tag("x", "y")
])
]).optimize()
const t = new Or([new Tag("a", "b"), new Or([new Tag("x", "y")])]).optimize()
expect(t).deep.eq(new Or([new Tag("a", "b"), new Tag("x", "y")]))
})
})
it("should not generate a conflict for climbing tags", () => {
const club_tags = TagUtils.Tag(
{
"or": [
"club=climbing",
{
"and": [
"sport=climbing",
{
"or": [
"office~*",
"club~*"
]
}
]
}
]
})
const club_tags = TagUtils.Tag({
or: [
"club=climbing",
{
and: [
"sport=climbing",
{
or: ["office~*", "club~*"],
},
],
},
],
})
const gym_tags = TagUtils.Tag({
"and": [
"sport=climbing",
"leisure=sports_centre"
]
and: ["sport=climbing", "leisure=sports_centre"],
})
const other_climbing = TagUtils.Tag({
"and": [
and: [
"sport=climbing",
"climbing!~route",
"leisure!~sports_centre",
"climbing!=route_top",
"climbing!=route_bottom"
]
"climbing!=route_bottom",
],
})
const together = new Or([club_tags, gym_tags, other_climbing])
const opt = together.optimize()
@ -319,17 +259,16 @@ describe("Tag optimalization", () => {
)
*/
expect(opt).deep.eq(
TagUtils.Tag({
or: [
"club=climbing",
{
and: ["sport=climbing",
{or: ["club~*", "office~*"]}]
and: ["sport=climbing", { or: ["club~*", "office~*"] }],
},
{
and: ["sport=climbing",
and: [
"sport=climbing",
{
or: [
"leisure=sports_centre",
@ -338,16 +277,15 @@ describe("Tag optimalization", () => {
"climbing!~route",
"climbing!=route_top",
"climbing!=route_bottom",
"leisure!~sports_centre"
]
}
]
}]
}
"leisure!~sports_centre",
],
},
],
},
],
},
],
})
)
})
})
})

View file

@ -1,52 +1,49 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {TagUtils} from "../../../Logic/Tags/TagUtils";
import {equal} from "assert";
import { describe } from "mocha"
import { expect } from "chai"
import { TagUtils } from "../../../Logic/Tags/TagUtils"
import { equal } from "assert"
describe("TagUtils", () => {
describe("ParseTag", () => {
it("should refuse a key!=* tag", () => {
expect(() => TagUtils.Tag("key!=*")).to.throw();
expect(() => TagUtils.Tag("key!=*")).to.throw()
})
it("should handle compare tag <=5", () => {
let compare = TagUtils.Tag("key<=5")
equal(compare.matchesProperties({"key": undefined}), false);
equal(compare.matchesProperties({"key": "6"}), false);
equal(compare.matchesProperties({"key": "5"}), true);
equal(compare.matchesProperties({"key": "4"}), true);
equal(compare.matchesProperties({ key: undefined }), false)
equal(compare.matchesProperties({ key: "6" }), false)
equal(compare.matchesProperties({ key: "5" }), true)
equal(compare.matchesProperties({ key: "4" }), true)
})
it("should handle compare tag < 5", () => {
const compare = TagUtils.Tag("key<5")
equal(compare.matchesProperties({"key": undefined}), false);
equal(compare.matchesProperties({"key": "6"}), false);
equal(compare.matchesProperties({"key": "5"}), false);
equal(compare.matchesProperties({"key": "4.2"}), true);
equal(compare.matchesProperties({ key: undefined }), false)
equal(compare.matchesProperties({ key: "6" }), false)
equal(compare.matchesProperties({ key: "5" }), false)
equal(compare.matchesProperties({ key: "4.2" }), true)
})
it("should handle compare tag >5", () => {
const compare = TagUtils.Tag("key>5")
equal(compare.matchesProperties({"key": undefined}), false);
equal(compare.matchesProperties({"key": "6"}), true);
equal(compare.matchesProperties({"key": "5"}), false);
equal(compare.matchesProperties({"key": "4.2"}), false);
equal(compare.matchesProperties({ key: undefined }), false)
equal(compare.matchesProperties({ key: "6" }), true)
equal(compare.matchesProperties({ key: "5" }), false)
equal(compare.matchesProperties({ key: "4.2" }), false)
})
it("should handle compare tag >=5", () => {
const compare = TagUtils.Tag("key>=5")
equal(compare.matchesProperties({"key": undefined}), false);
equal(compare.matchesProperties({"key": "6"}), true);
equal(compare.matchesProperties({"key": "5"}), true);
equal(compare.matchesProperties({"key": "4.2"}), false);
equal(compare.matchesProperties({ key: undefined }), false)
equal(compare.matchesProperties({ key: "6" }), true)
equal(compare.matchesProperties({ key: "5" }), true)
equal(compare.matchesProperties({ key: "4.2" }), false)
})
it("should handle date comparison tags", () => {
const filter = TagUtils.Tag("date_created<2022-01-07")
expect(filter.matchesProperties({"date_created": "2022-01-08"})).false
expect(filter.matchesProperties({"date_created": "2022-01-01"})).true
expect(filter.matchesProperties({ date_created: "2022-01-08" })).false
expect(filter.matchesProperties({ date_created: "2022-01-01" })).true
})
})
})

File diff suppressed because it is too large Load diff

View file

@ -1,32 +1,41 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {Utils} from "../../../../Utils";
import {DesugaringContext} from "../../../../Models/ThemeConfig/Conversion/Conversion";
import {LayerConfigJson} from "../../../../Models/ThemeConfig/Json/LayerConfigJson";
import {TagRenderingConfigJson} from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson";
import {PrepareLayer} from "../../../../Models/ThemeConfig/Conversion/PrepareLayer";
import * as bookcases from "../../../../assets/layers/public_bookcase/public_bookcase.json";
import CreateNoteImportLayer from "../../../../Models/ThemeConfig/Conversion/CreateNoteImportLayer";
import { describe } from "mocha"
import { expect } from "chai"
import { Utils } from "../../../../Utils"
import { DesugaringContext } from "../../../../Models/ThemeConfig/Conversion/Conversion"
import { LayerConfigJson } from "../../../../Models/ThemeConfig/Json/LayerConfigJson"
import { TagRenderingConfigJson } from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson"
import { PrepareLayer } from "../../../../Models/ThemeConfig/Conversion/PrepareLayer"
import * as bookcases from "../../../../assets/layers/public_bookcase/public_bookcase.json"
import CreateNoteImportLayer from "../../../../Models/ThemeConfig/Conversion/CreateNoteImportLayer"
describe("CreateNoteImportLayer", () => {
it("should generate a layerconfig", () => {
const desugaringState: DesugaringContext = {
sharedLayers: new Map<string, LayerConfigJson>(),
tagRenderings: new Map<string, TagRenderingConfigJson>()
}
const layerPrepare = new PrepareLayer(desugaringState)
const layer = layerPrepare.convertStrict(bookcases, "ImportLayerGeneratorTest:Parse bookcases")
const generator = new CreateNoteImportLayer()
const generatedLayer: LayerConfigJson = generator.convertStrict(layer, "ImportLayerGeneratorTest: convert")
expect(generatedLayer.isShown["and"][1].or[0].and[0]).deep.equal("_tags~(^|.*;)amenity=public_bookcase($|;.*)")
expect(generatedLayer.minzoom <= layer.minzoom, "Zoomlevel is to high").true
let renderings = Utils.NoNull(Utils.NoNull(generatedLayer.tagRenderings
.map(tr => (<TagRenderingConfigJson>tr).render))
.map(render => render["en"]))
expect(renderings.some(r => r.indexOf("import_button") > 0), "no import button found").true
})
it("should generate a layerconfig", () => {
const desugaringState: DesugaringContext = {
sharedLayers: new Map<string, LayerConfigJson>(),
tagRenderings: new Map<string, TagRenderingConfigJson>(),
}
const layerPrepare = new PrepareLayer(desugaringState)
const layer = layerPrepare.convertStrict(
bookcases,
"ImportLayerGeneratorTest:Parse bookcases"
)
const generator = new CreateNoteImportLayer()
const generatedLayer: LayerConfigJson = generator.convertStrict(
layer,
"ImportLayerGeneratorTest: convert"
)
expect(generatedLayer.isShown["and"][1].or[0].and[0]).deep.equal(
"_tags~(^|.*;)amenity=public_bookcase($|;.*)"
)
expect(generatedLayer.minzoom <= layer.minzoom, "Zoomlevel is to high").true
let renderings = Utils.NoNull(
Utils.NoNull(
generatedLayer.tagRenderings.map((tr) => (<TagRenderingConfigJson>tr).render)
).map((render) => render["en"])
)
expect(
renderings.some((r) => r.indexOf("import_button") > 0),
"no import button found"
).true
})
})

View file

@ -1,153 +1,142 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import LayoutConfig from "../../../../Models/ThemeConfig/LayoutConfig";
import {FixLegacyTheme} from "../../../../Models/ThemeConfig/Conversion/LegacyJsonConvert";
import { describe } from "mocha"
import { expect } from "chai"
import LayoutConfig from "../../../../Models/ThemeConfig/LayoutConfig"
import { FixLegacyTheme } from "../../../../Models/ThemeConfig/Conversion/LegacyJsonConvert"
describe("FixLegacyTheme", () => {
it("should create a working theme config", () => {
const walking_node_theme = {
"id": "walkingnodenetworks",
"title": {
"en": "Walking node networks"
},
"maintainer": "L'imaginaire",
"icon": "https://upload.wikimedia.org/wikipedia/commons/3/30/Man_walking_icon_1410105361.svg",
"description": {
"en": "This map shows walking node networks"
},
"language": [
"en"
],
socialImage: "img.jpg",
"version": "2021-10-02",
"startLat": 51.1599,
"startLon": 3.34750,
"startZoom": 12,
"clustering": {
"maxZoom": 12
},
"layers": [
{
"id": "node2node",
"name": {
"en": "node to node links"
},
"source": {
"osmTags": {
"and": [
"network=rwn",
"network:type=node_network"
]
}
},
"minzoom": 12,
"title": {
"render": {
"en": "node to node link"
},
"mappings": [
{
"if": "ref~*",
"then": {
"en": "node to node link <strong>{ref}</strong>"
}
}
]
},
"width": {
"render": "4"
},
"color": {
"render": "#8b1e20"
},
"tagRenderings": [
{
"question": {
"en": "When was this node to node link last surveyed?"
},
"render": {
"en": "This node to node link was last surveyed on {survey:date}"
},
"freeform": {
"key": "survey:date",
"type": "date"
},
"mappings": [
{
"if": "survey:date:={_now:date}",
"then": "Surveyed today!"
}
]
}
]
const walking_node_theme = {
id: "walkingnodenetworks",
title: {
en: "Walking node networks",
},
maintainer: "L'imaginaire",
icon: "https://upload.wikimedia.org/wikipedia/commons/3/30/Man_walking_icon_1410105361.svg",
description: {
en: "This map shows walking node networks",
},
language: ["en"],
socialImage: "img.jpg",
version: "2021-10-02",
startLat: 51.1599,
startLon: 3.3475,
startZoom: 12,
clustering: {
maxZoom: 12,
},
layers: [
{
id: "node2node",
name: {
en: "node to node links",
},
{
"id": "node",
"name": {
"en": "nodes"
source: {
osmTags: {
and: ["network=rwn", "network:type=node_network"],
},
"source": {
"osmTags": "rwn_ref~*"
},
minzoom: 12,
title: {
render: {
en: "node to node link",
},
"minzoom": 12,
"title": {
"render": {
"en": "walking node <strong>{rwn_ref}</strong>"
}
},
"label": {
"mappings": [
mappings: [
{
if: "ref~*",
then: {
en: "node to node link <strong>{ref}</strong>",
},
},
],
},
width: {
render: "4",
},
color: {
render: "#8b1e20",
},
tagRenderings: [
{
question: {
en: "When was this node to node link last surveyed?",
},
render: {
en: "This node to node link was last surveyed on {survey:date}",
},
freeform: {
key: "survey:date",
type: "date",
},
mappings: [
{
"if": "rwn_ref~*",
"then": "<div style='position: absolute; top: 10px; right: 10px; color: white; background-color: #8b1e20; width: 20px; height: 20px; border-radius: 100%'>{rwn_ref}</div>"
}
]
if: "survey:date:={_now:date}",
then: "Surveyed today!",
},
],
},
"tagRenderings": [
],
},
{
id: "node",
name: {
en: "nodes",
},
source: {
osmTags: "rwn_ref~*",
},
minzoom: 12,
title: {
render: {
en: "walking node <strong>{rwn_ref}</strong>",
},
},
label: {
mappings: [
{
"question": {
"en": "When was this walking node last surveyed?"
},
"render": {
"en": "This walking node was last surveyed on {survey:date}"
},
"freeform": {
"key": "survey:date",
"type": "date"
},
"mappings": [
{
"if": "survey:date:={_now:date}",
"then": "Surveyed today!"
}
]
if: "rwn_ref~*",
then: "<div style='position: absolute; top: 10px; right: 10px; color: white; background-color: #8b1e20; width: 20px; height: 20px; border-radius: 100%'>{rwn_ref}</div>",
},
{
"question": {
"en": "How many other walking nodes does this node link to?"
},
"render": {
"en": "This node links to {expected_rwn_route_relations} other walking nodes."
},
"freeform": {
"key": "expected_rwn_route_relations",
"type": "int"
}
],
},
tagRenderings: [
{
question: {
en: "When was this walking node last surveyed?",
},
"images"
]
}
]
}
const fixed = new FixLegacyTheme().convert(
<any> walking_node_theme,
"While testing")
expect(fixed.errors, "Could not fix the legacy theme").empty
const theme = new LayoutConfig(fixed.result, false)
expect(theme).not.undefined
render: {
en: "This walking node was last surveyed on {survey:date}",
},
freeform: {
key: "survey:date",
type: "date",
},
mappings: [
{
if: "survey:date:={_now:date}",
then: "Surveyed today!",
},
],
},
{
question: {
en: "How many other walking nodes does this node link to?",
},
render: {
en: "This node links to {expected_rwn_route_relations} other walking nodes.",
},
freeform: {
key: "expected_rwn_route_relations",
type: "int",
},
},
"images",
],
},
],
}
const fixed = new FixLegacyTheme().convert(<any>walking_node_theme, "While testing")
expect(fixed.errors, "Could not fix the legacy theme").empty
const theme = new LayoutConfig(fixed.result, false)
expect(theme).not.undefined
})
})

View file

@ -1,24 +1,24 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {LayerConfigJson} from "../../../../Models/ThemeConfig/Json/LayerConfigJson";
import {TagRenderingConfigJson} from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson";
import LineRenderingConfigJson from "../../../../Models/ThemeConfig/Json/LineRenderingConfigJson";
import {ExpandRewrite, PrepareLayer, RewriteSpecial} from "../../../../Models/ThemeConfig/Conversion/PrepareLayer";
import { describe } from "mocha"
import { expect } from "chai"
import { LayerConfigJson } from "../../../../Models/ThemeConfig/Json/LayerConfigJson"
import { TagRenderingConfigJson } from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson"
import LineRenderingConfigJson from "../../../../Models/ThemeConfig/Json/LineRenderingConfigJson"
import {
QuestionableTagRenderingConfigJson
} from "../../../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson";
import RewritableConfigJson from "../../../../Models/ThemeConfig/Json/RewritableConfigJson";
ExpandRewrite,
PrepareLayer,
RewriteSpecial,
} from "../../../../Models/ThemeConfig/Conversion/PrepareLayer"
import { QuestionableTagRenderingConfigJson } from "../../../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import RewritableConfigJson from "../../../../Models/ThemeConfig/Json/RewritableConfigJson"
describe("ExpandRewrite", () => {
it("should not allow overlapping keys", () => {
const spec = <RewritableConfigJson<string>>{
rewrite: {
sourceString: ["xyz", "longer_xyz"],
into: [["a", "b"], ["A, B"]],
},
renderings: "The value of xyz is longer_xyz"
renderings: "The value of xyz is longer_xyz",
}
const rewrite = new ExpandRewrite()
expect(() => rewrite.convert(spec, "test")).to.throw
@ -26,105 +26,111 @@ describe("ExpandRewrite", () => {
})
describe("PrepareLayer", () => {
it("should expand rewrites in map renderings", () => {
const exampleLayer: LayerConfigJson = {
id: "testlayer",
source: {
osmTags: "key=value"
osmTags: "key=value",
},
mapRendering: [
{
"rewrite": {
rewrite: {
sourceString: ["left|right", "lr_offset"],
into: [
["left", -6],
[ "right", +6],
]
["right", +6],
],
},
renderings: <LineRenderingConfigJson>{
"color": {
"render": "#888",
"mappings": [
color: {
render: "#888",
mappings: [
{
"if": "parking:condition:left|right=free",
"then": "#299921"
if: "parking:condition:left|right=free",
then: "#299921",
},
{
"if": "parking:condition:left|right=disc",
"then": "#219991"
}
]
if: "parking:condition:left|right=disc",
then: "#219991",
},
],
},
"offset": "lr_offset"
}
}
]
offset: "lr_offset",
},
},
],
}
const prep = new PrepareLayer({
tagRenderings: new Map<string, TagRenderingConfigJson>(),
sharedLayers: new Map<string, LayerConfigJson>()
sharedLayers: new Map<string, LayerConfigJson>(),
})
const result = prep.convertStrict(exampleLayer, "test")
const expected = {
"id": "testlayer",
"source": {"osmTags": "key=value"},
"mapRendering": [{
"color": {
"render": "#888",
"mappings": [{
"if": "parking:condition:left=free",
"then": "#299921"
id: "testlayer",
source: { osmTags: "key=value" },
mapRendering: [
{
color: {
render: "#888",
mappings: [
{
if: "parking:condition:left=free",
then: "#299921",
},
{
if: "parking:condition:left=disc",
then: "#219991",
},
],
},
{
"if": "parking:condition:left=disc",
"then": "#219991"
}]
offset: -6,
},
"offset": -6
}, {
"color": {
"render": "#888",
"mappings": [{
"if": "parking:condition:right=free",
"then": "#299921"
{
color: {
render: "#888",
mappings: [
{
if: "parking:condition:right=free",
then: "#299921",
},
{
if: "parking:condition:right=disc",
then: "#219991",
},
],
},
{
"if": "parking:condition:right=disc",
"then": "#219991"
}]
offset: 6,
},
"offset": 6
}],
"titleIcons": [{"render": "defaults", "id": "defaults"}]
],
titleIcons: [{ render: "defaults", id: "defaults" }],
}
expect(result).deep.eq(expected)
})
})
describe('RewriteSpecial', function () {
describe("RewriteSpecial", function () {
it("should rewrite the UK import button", () => {
const tr = <QuestionableTagRenderingConfigJson>{
"id": "uk_addresses_import_button",
"render": {
"special": {
"type": "import_button",
"targetLayer": "address",
"tags": "urpn_count=$urpn_count;ref:GB:uprn=$ref:GB:uprn$",
"text": "Add this address",
"icon": "./assets/themes/uk_addresses/housenumber_add.svg",
"location_picker": "none"
}
}
id: "uk_addresses_import_button",
render: {
special: {
type: "import_button",
targetLayer: "address",
tags: "urpn_count=$urpn_count;ref:GB:uprn=$ref:GB:uprn$",
text: "Add this address",
icon: "./assets/themes/uk_addresses/housenumber_add.svg",
location_picker: "none",
},
},
}
const r = new RewriteSpecial().convert(tr, "test").result
expect(r).to.deep.eq({
"id": "uk_addresses_import_button",
"render": {'*': "{import_button(address,urpn_count=$urpn_count;ref:GB:uprn=$ref:GB:uprn$,Add this address,./assets/themes/uk_addresses/housenumber_add.svg,,,,none,)}"}
id: "uk_addresses_import_button",
render: {
"*": "{import_button(address,urpn_count=$urpn_count;ref:GB:uprn=$ref:GB:uprn$,Add this address,./assets/themes/uk_addresses/housenumber_add.svg,,,,none,)}",
},
})
})
});
})

View file

@ -1,21 +1,19 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {LayoutConfigJson} from "../../../../Models/ThemeConfig/Json/LayoutConfigJson";
import {LayerConfigJson} from "../../../../Models/ThemeConfig/Json/LayerConfigJson";
import {PrepareTheme} from "../../../../Models/ThemeConfig/Conversion/PrepareTheme";
import {TagRenderingConfigJson} from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson";
import LayoutConfig from "../../../../Models/ThemeConfig/LayoutConfig";
import { describe } from "mocha"
import { expect } from "chai"
import { LayoutConfigJson } from "../../../../Models/ThemeConfig/Json/LayoutConfigJson"
import { LayerConfigJson } from "../../../../Models/ThemeConfig/Json/LayerConfigJson"
import { PrepareTheme } from "../../../../Models/ThemeConfig/Conversion/PrepareTheme"
import { TagRenderingConfigJson } from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson"
import LayoutConfig from "../../../../Models/ThemeConfig/LayoutConfig"
import * as bookcaseLayer from "../../../../assets/generated/layers/public_bookcase.json"
import LayerConfig from "../../../../Models/ThemeConfig/LayerConfig";
import {ExtractImages} from "../../../../Models/ThemeConfig/Conversion/FixImages";
import LayerConfig from "../../../../Models/ThemeConfig/LayerConfig"
import { ExtractImages } from "../../../../Models/ThemeConfig/Conversion/FixImages"
import * as cyclofix from "../../../../assets/generated/themes/cyclofix.json"
import {Tag} from "../../../../Logic/Tags/Tag";
import {DesugaringContext} from "../../../../Models/ThemeConfig/Conversion/Conversion";
import {And} from "../../../../Logic/Tags/And";
import { Tag } from "../../../../Logic/Tags/Tag"
import { DesugaringContext } from "../../../../Models/ThemeConfig/Conversion/Conversion"
import { And } from "../../../../Logic/Tags/And"
const themeConfigJson: LayoutConfigJson = {
description: "Descr",
icon: "",
layers: [
@ -23,137 +21,144 @@ const themeConfigJson: LayoutConfigJson = {
builtin: "public_bookcase",
override: {
source: {
geoJson: "xyz"
}
}
}
geoJson: "xyz",
},
},
},
],
startLat: 0,
startLon: 0,
startZoom: 0,
title: {
en: "Title"
en: "Title",
},
id: "test"
id: "test",
}
describe("PrepareTheme", () => {
it("should substitute layers", () => {
const sharedLayers = new Map<string, LayerConfigJson>()
sharedLayers.set("public_bookcase", bookcaseLayer["default"])
const theme ={...themeConfigJson, layers: ["public_bookcase"]}
const prepareStep = new PrepareTheme({
const theme = { ...themeConfigJson, layers: ["public_bookcase"] }
const prepareStep = new PrepareTheme({
tagRenderings: new Map<string, TagRenderingConfigJson>(),
sharedLayers: sharedLayers
sharedLayers: sharedLayers,
})
let themeConfigJsonPrepared = prepareStep.convert(theme, "test").result
const themeConfig = new LayoutConfig(themeConfigJsonPrepared);
const layerUnderTest = <LayerConfig> themeConfig.layers.find(l => l.id === "public_bookcase")
expect(layerUnderTest.source.osmTags).deep.eq(new And([new Tag("amenity","public_bookcase")]))
const themeConfig = new LayoutConfig(themeConfigJsonPrepared)
const layerUnderTest = <LayerConfig>(
themeConfig.layers.find((l) => l.id === "public_bookcase")
)
expect(layerUnderTest.source.osmTags).deep.eq(
new And([new Tag("amenity", "public_bookcase")])
)
})
it("should apply override", () => {
it("should apply override", () => {
const sharedLayers = new Map<string, LayerConfigJson>()
sharedLayers.set("public_bookcase", bookcaseLayer["default"])
let themeConfigJsonPrepared = new PrepareTheme({
tagRenderings: new Map<string, TagRenderingConfigJson>(),
sharedLayers: sharedLayers
}).convert( themeConfigJson, "test").result
const themeConfig = new LayoutConfig(themeConfigJsonPrepared);
const layerUnderTest = <LayerConfig> themeConfig.layers.find(l => l.id === "public_bookcase")
sharedLayers: sharedLayers,
}).convert(themeConfigJson, "test").result
const themeConfig = new LayoutConfig(themeConfigJsonPrepared)
const layerUnderTest = <LayerConfig>(
themeConfig.layers.find((l) => l.id === "public_bookcase")
)
expect(layerUnderTest.source.geojsonSource).eq("xyz")
})
it("should apply override", () => {
const sharedLayers = new Map<string, LayerConfigJson>()
sharedLayers.set("public_bookcase", bookcaseLayer["default"])
let themeConfigJsonPrepared = new PrepareTheme({
tagRenderings: new Map<string, TagRenderingConfigJson>(),
sharedLayers: sharedLayers
}).convert({...themeConfigJson, overrideAll: {source: {geoJson: "https://example.com/data.geojson"}}}, "test").result
const themeConfig = new LayoutConfig(themeConfigJsonPrepared);
const layerUnderTest = <LayerConfig> themeConfig.layers.find(l => l.id === "public_bookcase")
sharedLayers: sharedLayers,
}).convert(
{
...themeConfigJson,
overrideAll: { source: { geoJson: "https://example.com/data.geojson" } },
},
"test"
).result
const themeConfig = new LayoutConfig(themeConfigJsonPrepared)
const layerUnderTest = <LayerConfig>(
themeConfig.layers.find((l) => l.id === "public_bookcase")
)
expect(layerUnderTest.source.geojsonSource).eq("https://example.com/data.geojson")
})
it("should remove names which are overriden with null", () => {
const testLayer: LayerConfigJson = {
source: {
osmTags: "x=y"
osmTags: "x=y",
},
id: "layer-example",
name: {
en: "Test layer - please ignore"
en: "Test layer - please ignore",
},
titleIcons : [],
mapRendering: null
titleIcons: [],
mapRendering: null,
}
const ctx: DesugaringContext = {
sharedLayers: new Map<string, LayerConfigJson>([["layer-example", testLayer]]),
tagRenderings: new Map<string, TagRenderingConfigJson>(),
}
const layout: LayoutConfigJson = {
description: "A testing theme",
icon: "",
id: "",
layers: [
"layer-example",
{
builtin: "layer-example",
override: {
name: null,
minzoom: 18,
},
},
],
startLat: 0,
startLon: 0,
startZoom: 0,
title: "Test theme",
}
const ctx: DesugaringContext = {
sharedLayers: new Map<string, LayerConfigJson>([[
"layer-example", testLayer
]]),
tagRenderings: new Map<string, TagRenderingConfigJson>()
}
const layout : LayoutConfigJson=
{
description: "A testing theme",
icon: "",
id: "",
layers: [
"layer-example",
{
"builtin": "layer-example",
"override": {
"name": null,
"minzoom": 18
}
}
],
startLat: 0,
startLon: 0,
startZoom: 0,
title: "Test theme",
}
const rewritten = new PrepareTheme(ctx, {
skipDefaultLayers: true
skipDefaultLayers: true,
}).convertStrict(layout, "test")
expect(rewritten.layers[0]).deep.eq(testLayer)
expect(rewritten.layers[1]).deep.eq({
source: {
osmTags: "x=y"
osmTags: "x=y",
},
id: "layer-example",
name:null,
name: null,
minzoom: 18,
mapRendering: null,
titleIcons: []
titleIcons: [],
})
})
})
describe("ExtractImages", () => {
it("should find all images in a themefile", () => {
const images = new Set(new ExtractImages(true, new Map<string, any>()).convertStrict(<any> cyclofix, "test"))
const expectedValues = [
'./assets/layers/bike_repair_station/repair_station.svg',
'./assets/layers/bike_repair_station/repair_station_pump.svg',
'./assets/layers/bike_repair_station/broken_pump.svg',
'./assets/layers/bike_repair_station/pump.svg',
'./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg',
'./assets/layers/bike_repair_station/pump_example_manual.jpg',
'./assets/layers/bike_repair_station/pump_example.png',
'./assets/layers/bike_repair_station/pump_example_round.jpg',
'./assets/layers/bike_repair_station/repair_station_example_2.jpg',
'close']
for (const expected of expectedValues) {
expect(images).contains(expected)
}
const images = new Set(
new ExtractImages(true, new Map<string, any>()).convertStrict(<any>cyclofix, "test")
)
const expectedValues = [
"./assets/layers/bike_repair_station/repair_station.svg",
"./assets/layers/bike_repair_station/repair_station_pump.svg",
"./assets/layers/bike_repair_station/broken_pump.svg",
"./assets/layers/bike_repair_station/pump.svg",
"./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg",
"./assets/layers/bike_repair_station/pump_example_manual.jpg",
"./assets/layers/bike_repair_station/pump_example.png",
"./assets/layers/bike_repair_station/pump_example_round.jpg",
"./assets/layers/bike_repair_station/repair_station_example_2.jpg",
"close",
]
for (const expected of expectedValues) {
expect(images).contains(expected)
}
})
})
})

View file

@ -1,18 +1,18 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import SourceConfig from "../../../Models/ThemeConfig/SourceConfig";
import {TagUtils} from "../../../Logic/Tags/TagUtils";
import { describe } from "mocha"
import { expect } from "chai"
import SourceConfig from "../../../Models/ThemeConfig/SourceConfig"
import { TagUtils } from "../../../Logic/Tags/TagUtils"
describe("SourceConfig", () => {
it("should throw an error on conflicting tags", () => {
expect(() => {
new SourceConfig(
{
osmTags: TagUtils.Tag({
and: ["x=y", "a=b", "x!=y"]
})
}, false
and: ["x=y", "a=b", "x!=y"],
}),
},
false
)
}).to.throw(/tags are conflicting/)
})

View file

@ -1,71 +1,70 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
import Locale from "../../../UI/i18n/Locale";
import { describe } from "mocha"
import { expect } from "chai"
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig"
import Locale from "../../../UI/i18n/Locale"
describe("TagRenderingConfig", () => {
describe("isKnown", () => {
it("should give correct render values", () => {
Locale.language.setData("nl");
const tr = new TagRenderingConfig({
render: ({"en": "Name is {name}", "nl": "Ook een {name}"} as any),
question: "Wat is de naam van dit object?",
freeform: {
key: "name",
Locale.language.setData("nl")
const tr = new TagRenderingConfig(
{
render: { en: "Name is {name}", nl: "Ook een {name}" } as any,
question: "Wat is de naam van dit object?",
freeform: {
key: "name",
},
mappings: [
{
if: "noname=yes",
then: "Has no name",
},
],
condition: "x=",
},
"Tests"
)
mappings: [
{
if: "noname=yes",
"then": "Has no name"
}
],
condition: "x="
}, "Tests");
expect(tr.GetRenderValue({"foo": "bar"})).undefined
expect (tr.GetRenderValue({"noname": "yes"})?.textFor("nl")).eq("Has no name")
expect( tr.GetRenderValue({"name": "xyz"})?.textFor("nl")).eq("Ook een {name}")
expect( tr.GetRenderValue({"foo": "bar"})).undefined
expect(tr.GetRenderValue({ foo: "bar" })).undefined
expect(tr.GetRenderValue({ noname: "yes" })?.textFor("nl")).eq("Has no name")
expect(tr.GetRenderValue({ name: "xyz" })?.textFor("nl")).eq("Ook een {name}")
expect(tr.GetRenderValue({ foo: "bar" })).undefined
})
it("should give a correct indication", () => {
// tests a regression in parsing
const config = {
"#": "Bottle refill",
"question": {
"en": "How easy is it to fill water bottles?",
"nl": "Hoe gemakkelijk is het om drinkbussen bij te vullen?",
"de": "Wie einfach ist es, Wasserflaschen zu füllen?"
question: {
en: "How easy is it to fill water bottles?",
nl: "Hoe gemakkelijk is het om drinkbussen bij te vullen?",
de: "Wie einfach ist es, Wasserflaschen zu füllen?",
},
"mappings": [
mappings: [
{
"if": "bottle=yes",
"then": {
"en": "It is easy to refill water bottles",
"nl": "Een drinkbus bijvullen gaat makkelijk",
"de": "Es ist einfach, Wasserflaschen nachzufüllen"
}
if: "bottle=yes",
then: {
en: "It is easy to refill water bottles",
nl: "Een drinkbus bijvullen gaat makkelijk",
de: "Es ist einfach, Wasserflaschen nachzufüllen",
},
},
{
"if": "bottle=no",
"then": {
"en": "Water bottles may not fit",
"nl": "Een drinkbus past moeilijk",
"de": "Wasserflaschen passen möglicherweise nicht"
}
}
]
};
if: "bottle=no",
then: {
en: "Water bottles may not fit",
nl: "Een drinkbus past moeilijk",
de: "Wasserflaschen passen möglicherweise nicht",
},
},
],
}
const tagRendering = new TagRenderingConfig(config, "test");
expect(tagRendering.IsKnown({bottle: "yes"})).true
const tagRendering = new TagRenderingConfig(config, "test")
expect(tagRendering.IsKnown({ bottle: "yes" })).true
expect(tagRendering.IsKnown({})).false
})
})
})

View file

@ -1,29 +1,27 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {Unit} from "../../Models/Unit";
import {Denomination} from "../../Models/Denomination";
import { describe } from "mocha"
import { expect } from "chai"
import { Unit } from "../../Models/Unit"
import { Denomination } from "../../Models/Denomination"
describe("Unit", () => {
it("should convert a value back and forth", () => {
const denomintion = new Denomination({
"canonicalDenomination": "MW",
"alternativeDenomination": ["megawatts", "megawatt"],
"human": {
"en": " megawatts",
"nl": " megawatt"
it("should convert a value back and forth", () => {
const denomintion = new Denomination(
{
canonicalDenomination: "MW",
alternativeDenomination: ["megawatts", "megawatt"],
human: {
en: " megawatts",
nl: " megawatt",
},
}, "test");
},
"test"
)
const canonical = denomintion.canonicalValue("5", true)
expect(canonical).eq( "5 MW")
const units = new Unit(["key"], [denomintion], false)
const [detected, detectedDenom] = units.findDenomination("5 MW", () => "be")
expect(detected).eq( "5")
expect(detectedDenom).eq( denomintion)
}
)
const canonical = denomintion.canonicalValue("5", true)
expect(canonical).eq("5 MW")
const units = new Unit(["key"], [denomintion], false)
const [detected, detectedDenom] = units.findDenomination("5 MW", () => "be")
expect(detected).eq("5")
expect(detectedDenom).eq(denomintion)
})
})

View file

@ -1,15 +1,13 @@
import {describe} from 'mocha'
import {TagRenderingConfigJson} from "../../../Models/ThemeConfig/Json/TagRenderingConfigJson";
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig";
import TagRenderingQuestion from "../../../UI/Popup/TagRenderingQuestion";
import {UIEventSource} from "../../../Logic/UIEventSource";
import { expect } from 'chai';
import Locale from "../../../UI/i18n/Locale";
import { describe } from "mocha"
import { TagRenderingConfigJson } from "../../../Models/ThemeConfig/Json/TagRenderingConfigJson"
import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig"
import TagRenderingQuestion from "../../../UI/Popup/TagRenderingQuestion"
import { UIEventSource } from "../../../Logic/UIEventSource"
import { expect } from "chai"
import Locale from "../../../UI/i18n/Locale"
describe("TagRenderingQuestion", () => {
it("should have a freeform text field with the user defined placeholder", () => {
const configJson = <TagRenderingConfigJson>{
id: "test-tag-rendering",
question: "Question?",
@ -17,17 +15,18 @@ describe("TagRenderingQuestion", () => {
freeform: {
key: "capacity",
type: "pnat",
placeholder: "Some user defined placeholder"
}
placeholder: "Some user defined placeholder",
},
}
const config = new TagRenderingConfig(configJson, "test")
const ui = new TagRenderingQuestion( new UIEventSource<any>({}), config)
const ui = new TagRenderingQuestion(new UIEventSource<any>({}), config)
const html = ui.ConstructElement()
expect(html.getElementsByTagName("input")[0]["placeholder"]).eq("Some user defined placeholder")
expect(html.getElementsByTagName("input")[0]["placeholder"]).eq(
"Some user defined placeholder"
)
})
it("should have a freeform text field with a type explanation", () => {
Locale.language.setData("en")
const configJson = <TagRenderingConfigJson>{
id: "test-tag-rendering",
@ -36,12 +35,13 @@ describe("TagRenderingQuestion", () => {
freeform: {
key: "capacity",
type: "pnat",
}
},
}
const config = new TagRenderingConfig(configJson, "test")
const ui = new TagRenderingQuestion( new UIEventSource<any>({}), config)
const ui = new TagRenderingQuestion(new UIEventSource<any>({}), config)
const html = ui.ConstructElement()
expect(html.getElementsByTagName("input")[0]["placeholder"])
.eq("capacity (a positive, whole number)")
expect(html.getElementsByTagName("input")[0]["placeholder"]).eq(
"capacity (a positive, whole number)"
)
})
})

View file

@ -1,19 +1,23 @@
import {describe} from 'mocha'
import SpecialVisualizations from "../../UI/SpecialVisualizations";
import {expect} from "chai";
import { describe } from "mocha"
import SpecialVisualizations from "../../UI/SpecialVisualizations"
import { expect } from "chai"
describe("SpecialVisualisations", () => {
describe("predifined special visualisations", () => {
it("should not have an argument called 'type'", () => {
const specials = SpecialVisualizations.specialVisualizations
for (const special of specials) {
expect(special.funcName).not.eq('type', "A special visualisation is not allowed to be named 'type', as this will conflict with the 'special'-blocks")
expect(special.funcName).not.eq(
"type",
"A special visualisation is not allowed to be named 'type', as this will conflict with the 'special'-blocks"
)
for (const arg of special.args) {
expect(arg.name).not.eq('type', "An argument is not allowed to be called 'type', as this will conflict with the 'special'-blocks")
expect(arg.name).not.eq(
"type",
"An argument is not allowed to be called 'type', as this will conflict with the 'special'-blocks"
)
}
}
})
})
})
})

View file

@ -1,17 +1,20 @@
import {describe} from 'mocha'
import ValidatedTextField from "../../UI/Input/ValidatedTextField";
import {fail} from "assert";
import Translations from "../../UI/i18n/Translations";
import { describe } from "mocha"
import ValidatedTextField from "../../UI/Input/ValidatedTextField"
import { fail } from "assert"
import Translations from "../../UI/i18n/Translations"
describe("ValidatedTextFields", () => {
it("should all have description in the translations", () => {
const ts = Translations.t.validation;
const ts = Translations.t.validation
const missingTranslations = Array.from(ValidatedTextField.allTypes.keys())
.filter(key => ts[key] === undefined || ts[key].description === undefined)
.filter(key => key !== "distance")
.filter((key) => ts[key] === undefined || ts[key].description === undefined)
.filter((key) => key !== "distance")
if (missingTranslations.length > 0) {
fail("The validated text fields don't have a description defined in en.json for "+missingTranslations.join(", ")+". (Did you just add one? Run `npm run generate:translations`)")
fail(
"The validated text fields don't have a description defined in en.json for " +
missingTranslations.join(", ") +
". (Did you just add one? Run `npm run generate:translations`)"
)
}
})
})

View file

@ -1,75 +1,60 @@
import {Utils} from "../Utils";
import LZString from "lz-string";
import {describe} from 'mocha'
import {expect} from 'chai'
import { Utils } from "../Utils"
import LZString from "lz-string"
import { describe } from "mocha"
import { expect } from "chai"
const example = {
"id": "bookcases",
"maintainer": "MapComplete",
"version": "2020-08-29",
"language": [
"en",
"nl",
"de",
"fr"
],
"title": {
"en": "Open Bookcase Map",
"nl": "Open Boekenruilkastenkaart",
"de": "Öffentliche Bücherschränke Karte",
"fr": "Carte des microbibliothèques"
id: "bookcases",
maintainer: "MapComplete",
version: "2020-08-29",
language: ["en", "nl", "de", "fr"],
title: {
en: "Open Bookcase Map",
nl: "Open Boekenruilkastenkaart",
de: "Öffentliche Bücherschränke Karte",
fr: "Carte des microbibliothèques",
},
"description": {
"en": "A public bookcase is a small streetside cabinet, box, old phone boot or some other objects where books are stored. Everyone can place or take a book. This map aims to collect all these bookcases. You can discover new bookcases nearby and, with a free OpenStreetMap account, quickly add your favourite bookcases.",
"nl": "Een boekenruilkast is een kastje waar iedereen een boek kan nemen of achterlaten. Op deze kaart kan je deze boekenruilkasten terugvinden en met een gratis OpenStreetMap-account, ook boekenruilkasten toevoegen of informatie verbeteren",
"de": "Ein öffentlicher Bücherschrank ist ein kleiner Bücherschrank am Straßenrand, ein Kasten, eine alte Telefonzelle oder andere Gegenstände, in denen Bücher aufbewahrt werden. Jeder kann ein Buch hinstellen oder mitnehmen. Diese Karte zielt darauf ab, all diese Bücherschränke zu sammeln. Sie können neue Bücherschränke in der Nähe entdecken und mit einem kostenlosen OpenStreetMap-Account schnell Ihre Lieblingsbücherschränke hinzufügen.",
"fr": "Une microbibliothèques, également appelée boite à livre, est un élément de mobilier urbain (étagère, armoire, etc) dans lequel sont stockés des livres et autres objets en accès libre. Découvrez les boites à livres prêt de chez vous, ou ajouter en une nouvelle à l'aide de votre compte OpenStreetMap."
description: {
en: "A public bookcase is a small streetside cabinet, box, old phone boot or some other objects where books are stored. Everyone can place or take a book. This map aims to collect all these bookcases. You can discover new bookcases nearby and, with a free OpenStreetMap account, quickly add your favourite bookcases.",
nl: "Een boekenruilkast is een kastje waar iedereen een boek kan nemen of achterlaten. Op deze kaart kan je deze boekenruilkasten terugvinden en met een gratis OpenStreetMap-account, ook boekenruilkasten toevoegen of informatie verbeteren",
de: "Ein öffentlicher Bücherschrank ist ein kleiner Bücherschrank am Straßenrand, ein Kasten, eine alte Telefonzelle oder andere Gegenstände, in denen Bücher aufbewahrt werden. Jeder kann ein Buch hinstellen oder mitnehmen. Diese Karte zielt darauf ab, all diese Bücherschränke zu sammeln. Sie können neue Bücherschränke in der Nähe entdecken und mit einem kostenlosen OpenStreetMap-Account schnell Ihre Lieblingsbücherschränke hinzufügen.",
fr: "Une microbibliothèques, également appelée boite à livre, est un élément de mobilier urbain (étagère, armoire, etc) dans lequel sont stockés des livres et autres objets en accès libre. Découvrez les boites à livres prêt de chez vous, ou ajouter en une nouvelle à l'aide de votre compte OpenStreetMap.",
},
"icon": "./assets/themes/bookcases/bookcase.svg",
"socialImage": null,
"startLat": 0,
"startLon": 0,
"startZoom": 1,
"widenFactor": 0.05,
"roamingRenderings": [],
"layers": [
"public_bookcase"
]
icon: "./assets/themes/bookcases/bookcase.svg",
socialImage: null,
startLat: 0,
startLon: 0,
startZoom: 1,
widenFactor: 0.05,
roamingRenderings: [],
layers: ["public_bookcase"],
}
describe("Utils", () => {
describe("Minify-json", () => {
it("should work in two directions", () => {
const str = JSON.stringify({title: "abc", "and": "xyz", "render": "somevalue"});
const minified = Utils.MinifyJSON(str);
const str = JSON.stringify({ title: "abc", and: "xyz", render: "somevalue" })
const minified = Utils.MinifyJSON(str)
const restored = Utils.UnMinify(minified)
expect(str).eq(restored)
})
it("should minify and restore the bookcase example", () => {
const str = JSON.stringify(example, null, 0)
const minified = Utils.MinifyJSON(str);
const minified = Utils.MinifyJSON(str)
const restored = Utils.UnMinify(minified)
expect(str).eq(restored)
})
it("should LZ-compress a theme", () => {
const str = JSON.stringify(example, null, 0)
const minified = LZString.compressToBase64(Utils.MinifyJSON(str));
const minified = LZString.compressToBase64(Utils.MinifyJSON(str))
const restored = Utils.UnMinify(LZString.decompressFromBase64(minified))
expect(str).eq(restored)
})
it("shoud be able to decode the LZ-compression of a theme", () => {
const str = JSON.stringify(example, null, 0)
const minified = LZString.compressToBase64(str);
const minified = LZString.compressToBase64(str)
const restored = LZString.decompressFromBase64(minified)
expect(str).eq(restored)
})
})
})

File diff suppressed because one or more lines are too long

View file

@ -1,32 +1,41 @@
import ScriptUtils from "../scripts/ScriptUtils";
import {Utils} from "../Utils";
import ScriptUtils from "../scripts/ScriptUtils"
import { Utils } from "../Utils"
import * as fakedom from "fake-dom"
import Locale from "../UI/i18n/Locale";
import Locale from "../UI/i18n/Locale"
export const mochaHooks = {
beforeEach(done) {
ScriptUtils.fixUtils();
ScriptUtils.fixUtils()
Locale.language.setData("en")
if (fakedom === undefined || window === undefined) {
throw "FakeDom not initialized"
}
// Block internet access
const realDownloadFunc = Utils.externalDownloadFunction;
const realDownloadFunc = Utils.externalDownloadFunction
Utils.externalDownloadFunction = async (url) => {
console.error("Fetching ", url, "blocked in tests, use Utils.injectJsonDownloadForTests")
console.error(
"Fetching ",
url,
"blocked in tests, use Utils.injectJsonDownloadForTests"
)
const data = await realDownloadFunc(url)
console.log("\n\n ----------- \nBLOCKED DATA\n Utils.injectJsonDownloadForTests(\n" +
" ", JSON.stringify(url), ", \n",
" ", JSON.stringify(data), "\n )\n------------------\n\n")
throw new Error("Detected internet access for URL " + url + ", please inject it with Utils.injectJsonDownloadForTests")
console.log(
"\n\n ----------- \nBLOCKED DATA\n Utils.injectJsonDownloadForTests(\n" + " ",
JSON.stringify(url),
", \n",
" ",
JSON.stringify(data),
"\n )\n------------------\n\n"
)
throw new Error(
"Detected internet access for URL " +
url +
", please inject it with Utils.injectJsonDownloadForTests"
)
}
done();
}
}
done()
},
}