Do not show out-of-range features on speelplekken layer, fix handling of mutlipolygons in 'inside', better tests
This commit is contained in:
parent
117b0bddb1
commit
6f457a6f0d
26 changed files with 1284 additions and 770 deletions
197
test/GeoOperations.spec.ts
Normal file
197
test/GeoOperations.spec.ts
Normal file
|
@ -0,0 +1,197 @@
|
|||
import {Utils} from "../Utils";
|
||||
|
||||
Utils.runningFromConsole = true;
|
||||
import {equal} from "assert";
|
||||
import T from "./TestHelper";
|
||||
import {FromJSON} from "../Customizations/JSON/FromJSON";
|
||||
import Locale from "../UI/i18n/Locale";
|
||||
import Translations from "../UI/i18n/Translations";
|
||||
import {UIEventSource} from "../Logic/UIEventSource";
|
||||
import TagRenderingConfig from "../Customizations/JSON/TagRenderingConfig";
|
||||
import EditableTagRendering from "../UI/Popup/EditableTagRendering";
|
||||
import {Translation} from "../UI/i18n/Translation";
|
||||
import {OH, OpeningHour} from "../UI/OpeningHours/OpeningHours";
|
||||
import PublicHolidayInput from "../UI/OpeningHours/PublicHolidayInput";
|
||||
import {SubstitutedTranslation} from "../UI/SubstitutedTranslation";
|
||||
import {Tag} from "../Logic/Tags/Tag";
|
||||
import {And} from "../Logic/Tags/And";
|
||||
import * as Assert from "assert";
|
||||
import {GeoOperations} from "../Logic/GeoOperations";
|
||||
|
||||
export default class GeoOperationsSpec extends T {
|
||||
|
||||
private static polygon = {
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
1.8017578124999998,
|
||||
50.401515322782366
|
||||
],
|
||||
[
|
||||
-3.1640625,
|
||||
46.255846818480315
|
||||
],
|
||||
[
|
||||
5.185546875,
|
||||
44.74673324024678
|
||||
],
|
||||
[
|
||||
1.8017578124999998,
|
||||
50.401515322782366
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
};
|
||||
private static multiPolygon = {
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [[
|
||||
[
|
||||
[
|
||||
1.8017578124999998,
|
||||
50.401515322782366
|
||||
],
|
||||
[
|
||||
-3.1640625,
|
||||
46.255846818480315
|
||||
],
|
||||
[
|
||||
5.185546875,
|
||||
44.74673324024678
|
||||
],
|
||||
[
|
||||
1.8017578124999998,
|
||||
50.401515322782366
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
1.0107421875,
|
||||
48.821332549646634
|
||||
],
|
||||
[
|
||||
1.329345703125,
|
||||
48.25394114463431
|
||||
],
|
||||
[
|
||||
1.988525390625,
|
||||
48.71271258145237
|
||||
],
|
||||
[
|
||||
0.999755859375,
|
||||
48.86471476180277
|
||||
],
|
||||
[
|
||||
1.0107421875,
|
||||
48.821332549646634
|
||||
]
|
||||
]
|
||||
]]
|
||||
}
|
||||
};
|
||||
|
||||
private static inHole = [1.42822265625, 48.61838518688487]
|
||||
private static inMultiPolygon = [2.515869140625, 47.37603463349758]
|
||||
private static outsidePolygon = [4.02099609375, 47.81315451752768]
|
||||
|
||||
constructor() {
|
||||
super(
|
||||
"GeoOperationsSpec", [
|
||||
["Point out of polygon", () => {
|
||||
GeoOperationsSpec.isFalse(GeoOperations.inside([
|
||||
3.779296875,
|
||||
48.777912755501845
|
||||
], GeoOperationsSpec.polygon), "Point is outside of the polygon");
|
||||
}
|
||||
|
||||
],
|
||||
["Point inside of polygon", () => {
|
||||
|
||||
GeoOperationsSpec.isTrue(GeoOperations.inside([
|
||||
1.23046875,
|
||||
47.60616304386874
|
||||
], GeoOperationsSpec.polygon), "Point is inside of the polygon");
|
||||
}
|
||||
],
|
||||
["MultiPolygonTest", () => {
|
||||
|
||||
const isTrue = GeoOperationsSpec.isTrue;
|
||||
const isFalse = GeoOperationsSpec.isFalse;
|
||||
|
||||
isFalse(GeoOperations.inside(GeoOperationsSpec.inHole, GeoOperationsSpec.multiPolygon), "InHole was detected as true");
|
||||
isTrue(GeoOperations.inside(GeoOperationsSpec.inMultiPolygon, GeoOperationsSpec.multiPolygon), "InMultiPolgyon was not detected as true");
|
||||
isFalse(GeoOperations.inside(GeoOperationsSpec.outsidePolygon, GeoOperationsSpec.multiPolygon), "OutsideOfPolygon was detected as true");
|
||||
|
||||
}],
|
||||
["Intersection between a line and a polygon", () => {
|
||||
const line = {
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
3.779296875,
|
||||
48.777912755501845
|
||||
],
|
||||
[
|
||||
1.23046875,
|
||||
47.60616304386874
|
||||
]
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const overlap = GeoOperations.calculateOverlap(line, [GeoOperationsSpec.polygon]);
|
||||
Assert.equal(1, overlap.length)
|
||||
}],
|
||||
["Fully enclosed", () => {
|
||||
const line = {
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
0.0439453125,
|
||||
47.31648293428332
|
||||
],
|
||||
[
|
||||
0.6591796875,
|
||||
46.77749276376827
|
||||
]
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const overlap = GeoOperations.calculateOverlap(line, [GeoOperationsSpec.polygon]);
|
||||
Assert.equal(1, overlap.length)
|
||||
}],
|
||||
["overlapWith matches points too", () => {
|
||||
const point = {
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
2.274169921875,
|
||||
46.76244305208004
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const overlap = GeoOperations.calculateOverlap(point, [GeoOperationsSpec.polygon]);
|
||||
Assert.equal(1, overlap.length)
|
||||
}]
|
||||
]
|
||||
)
|
||||
|
||||
}
|
||||
}
|
|
@ -20,39 +20,43 @@ import {AllKnownLayouts} from "../Customizations/AllKnownLayouts";
|
|||
import AllKnownLayers from "../Customizations/AllKnownLayers";
|
||||
import LayerConfig from "../Customizations/JSON/LayerConfig";
|
||||
|
||||
export default class ImageAttributionSpec extends T {
|
||||
constructor() {
|
||||
super(
|
||||
"ImageAttribution Tests", [
|
||||
[
|
||||
"Should find all the images",
|
||||
() => {
|
||||
const pumps: LayerConfig = AllKnownLayers.sharedLayers["bike_repair_station"]
|
||||
const images = pumps.ExtractImages();
|
||||
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_2.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.jpg']
|
||||
for (const expected of expectedValues) {
|
||||
T.isTrue(images.has(expected), expected + " not found")
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
"Test image discovery regex",
|
||||
() => {
|
||||
const tr = new Translation({en: "XYZ <img src='a.svg'/> XYZ <img src=\"some image.svg\"></img> XYZ <img src=b.svg/>"})
|
||||
const images = new Set<string>(tr.ExtractImages(false));
|
||||
equal(3, images.size)
|
||||
T.isTrue(images.has("a.svg"), "a.svg not found")
|
||||
T.isTrue(images.has("b.svg"), "b.svg not found")
|
||||
T.isTrue(images.has("some image.svg"), "some image.svg not found")
|
||||
|
||||
new T("ImageAttribution Tests", [
|
||||
[
|
||||
"Should find all the images",
|
||||
() => {
|
||||
const pumps: LayerConfig = AllKnownLayers.sharedLayers["bike_repair_station"]
|
||||
const images = pumps.ExtractImages();
|
||||
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_2.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.jpg']
|
||||
for (const expected of expectedValues) {
|
||||
T.isTrue(images.has(expected), expected + " not found")
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
"Test image discovery regex",
|
||||
() => {
|
||||
const tr = new Translation({en: "XYZ <img src='a.svg'/> XYZ <img src=\"some image.svg\"></img> XYZ <img src=b.svg/>"})
|
||||
const images = new Set<string>(tr.ExtractImages(false));
|
||||
equal(3, images.size)
|
||||
T.isTrue(images.has("a.svg"), "a.svg not found")
|
||||
T.isTrue(images.has("b.svg"), "b.svg not found")
|
||||
T.isTrue(images.has("some image.svg"), "some image.svg not found")
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -16,20 +16,26 @@ import {SubstitutedTranslation} from "../UI/SubstitutedTranslation";
|
|||
import {Tag} from "../Logic/Tags/Tag";
|
||||
import {And} from "../Logic/Tags/And";
|
||||
import {ImageSearcher} from "../Logic/Actors/ImageSearcher";
|
||||
export default class ImageSearcherSpec extends T {
|
||||
|
||||
constructor() {
|
||||
super("ImageSearcher", [
|
||||
[
|
||||
"Should find images",
|
||||
() => {
|
||||
const tags = new UIEventSource({
|
||||
"mapillary": "https://www.mapillary.com/app/?pKey=bYH6FFl8LXAPapz4PNSh3Q"
|
||||
});
|
||||
const searcher = ImageSearcher.construct(tags)
|
||||
const result = searcher.data[0];
|
||||
equal(result.url, "https://www.mapillary.com/map/im/bYH6FFl8LXAPapz4PNSh3Q");
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
new T("ImageSearcher", [
|
||||
[
|
||||
"Should find images",
|
||||
() => {
|
||||
const tags = new UIEventSource({
|
||||
"mapillary": "https://www.mapillary.com/app/?pKey=bYH6FFl8LXAPapz4PNSh3Q"
|
||||
});
|
||||
const searcher = ImageSearcher.construct(tags)
|
||||
const result = searcher.data[0];
|
||||
equal(result.url, "https://www.mapillary.com/map/im/bYH6FFl8LXAPapz4PNSh3Q");
|
||||
}
|
||||
]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
])
|
||||
}
|
||||
|
|
752
test/Tag.spec.ts
752
test/Tag.spec.ts
|
@ -1,6 +1,4 @@
|
|||
import {Utils} from "../Utils";
|
||||
|
||||
Utils.runningFromConsole = true;
|
||||
import {equal} from "assert";
|
||||
import T from "./TestHelper";
|
||||
import {FromJSON} from "../Customizations/JSON/FromJSON";
|
||||
|
@ -15,414 +13,420 @@ import PublicHolidayInput from "../UI/OpeningHours/PublicHolidayInput";
|
|||
import {SubstitutedTranslation} from "../UI/SubstitutedTranslation";
|
||||
import {Tag} from "../Logic/Tags/Tag";
|
||||
import {And} from "../Logic/Tags/And";
|
||||
import * as Assert from "assert";
|
||||
|
||||
Utils.runningFromConsole = true;
|
||||
|
||||
export default class TagSpec extends T{
|
||||
|
||||
constructor() {
|
||||
super("Tags", [
|
||||
["Tag replacement works in translation", () => {
|
||||
const tr = new Translation({
|
||||
"en": "Test {key} abc"
|
||||
}).replace("{key}", "value");
|
||||
equal(tr.txt, "Test value abc");
|
||||
|
||||
}],
|
||||
["Parse tag config", (() => {
|
||||
const tag = FromJSON.Tag("key=value") as Tag;
|
||||
equal(tag.key, "key");
|
||||
equal(tag.value, "value");
|
||||
equal(tag.matchesProperties({"key": "value"}), true)
|
||||
equal(tag.matchesProperties({"key": "z"}), false)
|
||||
equal(tag.matchesProperties({"key": ""}), false)
|
||||
equal(tag.matchesProperties({"other_key": ""}), false)
|
||||
equal(tag.matchesProperties({"other_key": "value"}), false)
|
||||
|
||||
const isEmpty = FromJSON.Tag("key=") as Tag;
|
||||
equal(isEmpty.matchesProperties({"key": "value"}), false)
|
||||
equal(isEmpty.matchesProperties({"key": ""}), true)
|
||||
equal(isEmpty.matchesProperties({"other_key": ""}), true)
|
||||
equal(isEmpty.matchesProperties({"other_key": "value"}), true)
|
||||
|
||||
const isNotEmpty = FromJSON.Tag("key!=");
|
||||
equal(isNotEmpty.matchesProperties({"key": "value"}), true)
|
||||
equal(isNotEmpty.matchesProperties({"key": "other_value"}), true)
|
||||
equal(isNotEmpty.matchesProperties({"key": ""}), false)
|
||||
equal(isNotEmpty.matchesProperties({"other_key": ""}), false)
|
||||
equal(isNotEmpty.matchesProperties({"other_key": "value"}), false)
|
||||
|
||||
|
||||
new T("Tags", [
|
||||
["Tag replacement works in translation", () => {
|
||||
const tr = new Translation({
|
||||
"en": "Test {key} abc"
|
||||
}).replace("{key}", "value");
|
||||
equal(tr.txt, "Test value abc");
|
||||
|
||||
}],
|
||||
["Parse tag config", (() => {
|
||||
const tag = FromJSON.Tag("key=value") as Tag;
|
||||
equal(tag.key, "key");
|
||||
equal(tag.value, "value");
|
||||
equal(tag.matchesProperties({"key": "value"}), true)
|
||||
equal(tag.matchesProperties({"key": "z"}), false)
|
||||
equal(tag.matchesProperties({"key": ""}), false)
|
||||
equal(tag.matchesProperties({"other_key": ""}), false)
|
||||
equal(tag.matchesProperties({"other_key": "value"}), false)
|
||||
|
||||
const isEmpty = FromJSON.Tag("key=") as Tag;
|
||||
equal(isEmpty.matchesProperties({"key": "value"}), false)
|
||||
equal(isEmpty.matchesProperties({"key": ""}), true)
|
||||
equal(isEmpty.matchesProperties({"other_key": ""}), true)
|
||||
equal(isEmpty.matchesProperties({"other_key": "value"}), true)
|
||||
|
||||
const isNotEmpty = FromJSON.Tag("key!=");
|
||||
equal(isNotEmpty.matchesProperties({"key": "value"}), true)
|
||||
equal(isNotEmpty.matchesProperties({"key": "other_value"}), true)
|
||||
equal(isNotEmpty.matchesProperties({"key": ""}), false)
|
||||
equal(isNotEmpty.matchesProperties({"other_key": ""}), false)
|
||||
equal(isNotEmpty.matchesProperties({"other_key": "value"}), false)
|
||||
const and = FromJSON.Tag({"and": ["key=value", "x=y"]}) as And;
|
||||
equal((and.and[0] as Tag).key, "key");
|
||||
equal((and.and[1] as Tag).value, "y");
|
||||
|
||||
|
||||
const and = FromJSON.Tag({"and": ["key=value", "x=y"]}) as And;
|
||||
equal((and.and[0] as Tag).key, "key");
|
||||
equal((and.and[1] as Tag).value, "y");
|
||||
const notReg = FromJSON.Tag("x!~y") as And;
|
||||
equal(notReg.matchesProperties({"x": "y"}), false)
|
||||
equal(notReg.matchesProperties({"x": "z"}), true)
|
||||
equal(notReg.matchesProperties({"x": ""}), true)
|
||||
equal(notReg.matchesProperties({}), true)
|
||||
|
||||
const noMatch = FromJSON.Tag("key!=value") as Tag;
|
||||
equal(noMatch.matchesProperties({"key": "value"}), false)
|
||||
equal(noMatch.matchesProperties({"key": "otherValue"}), true)
|
||||
equal(noMatch.matchesProperties({"key": ""}), true)
|
||||
equal(noMatch.matchesProperties({"otherKey": ""}), true)
|
||||
|
||||
|
||||
const notReg = FromJSON.Tag("x!~y") as And;
|
||||
equal(notReg.matchesProperties({"x": "y"}), false)
|
||||
equal(notReg.matchesProperties({"x": "z"}), true)
|
||||
equal(notReg.matchesProperties({"x": ""}), true)
|
||||
equal(notReg.matchesProperties({}), true)
|
||||
const multiMatch = FromJSON.Tag("vending~.*bicycle_tube.*") as Tag;
|
||||
equal(multiMatch.matchesProperties({"vending": "bicycle_tube"}), true)
|
||||
equal(multiMatch.matchesProperties({"vending": "something;bicycle_tube"}), true)
|
||||
equal(multiMatch.matchesProperties({"vending": "bicycle_tube;something"}), true)
|
||||
equal(multiMatch.matchesProperties({"vending": "xyz;bicycle_tube;something"}), true)
|
||||
|
||||
const noMatch = FromJSON.Tag("key!=value") as Tag;
|
||||
equal(noMatch.matchesProperties({"key": "value"}), false)
|
||||
equal(noMatch.matchesProperties({"key": "otherValue"}), true)
|
||||
equal(noMatch.matchesProperties({"key": ""}), true)
|
||||
equal(noMatch.matchesProperties({"otherKey": ""}), true)
|
||||
const nameStartsWith = FromJSON.Tag("name~[sS]peelbos.*")
|
||||
equal(nameStartsWith.matchesProperties({"name": "Speelbos Sint-Anna"}), true)
|
||||
equal(nameStartsWith.matchesProperties({"name": "speelbos Sint-Anna"}), true)
|
||||
equal(nameStartsWith.matchesProperties({"name": "Sint-Anna"}), false)
|
||||
equal(nameStartsWith.matchesProperties({"name": ""}), false)
|
||||
|
||||
|
||||
const multiMatch = FromJSON.Tag("vending~.*bicycle_tube.*") as Tag;
|
||||
equal(multiMatch.matchesProperties({"vending": "bicycle_tube"}), true)
|
||||
equal(multiMatch.matchesProperties({"vending": "something;bicycle_tube"}), true)
|
||||
equal(multiMatch.matchesProperties({"vending": "bicycle_tube;something"}), true)
|
||||
equal(multiMatch.matchesProperties({"vending": "xyz;bicycle_tube;something"}), true)
|
||||
const assign = FromJSON.Tag("survey:date:={_date:now}")
|
||||
equal(assign.matchesProperties({"survey:date": "2021-03-29", "_date:now": "2021-03-29"}), true);
|
||||
equal(assign.matchesProperties({"survey:date": "2021-03-29", "_date:now": "2021-01-01"}), false);
|
||||
equal(assign.matchesProperties({"survey:date": "2021-03-29"}), false);
|
||||
equal(assign.matchesProperties({"_date:now": "2021-03-29"}), false);
|
||||
equal(assign.matchesProperties({"some_key": "2021-03-29"}), false);
|
||||
|
||||
const nameStartsWith = FromJSON.Tag("name~[sS]peelbos.*")
|
||||
equal(nameStartsWith.matchesProperties({"name": "Speelbos Sint-Anna"}), true)
|
||||
equal(nameStartsWith.matchesProperties({"name": "speelbos Sint-Anna"}), true)
|
||||
equal(nameStartsWith.matchesProperties({"name": "Sint-Anna"}), false)
|
||||
equal(nameStartsWith.matchesProperties({"name": ""}), false)
|
||||
})],
|
||||
["Is equivalent test", (() => {
|
||||
|
||||
const t0 = new And([
|
||||
new Tag("valves:special", "A"),
|
||||
new Tag("valves", "A")
|
||||
])
|
||||
const t1 = new And([
|
||||
new Tag("valves", "A")
|
||||
])
|
||||
const t2 = new And([
|
||||
new Tag("valves", "B")
|
||||
])
|
||||
equal(true, t0.isEquivalent(t0))
|
||||
equal(true, t1.isEquivalent(t1))
|
||||
equal(true, t2.isEquivalent(t2))
|
||||
|
||||
const assign = FromJSON.Tag("survey:date:={_date:now}")
|
||||
equal(assign.matchesProperties({"survey:date": "2021-03-29", "_date:now": "2021-03-29"}), true);
|
||||
equal(assign.matchesProperties({"survey:date": "2021-03-29", "_date:now": "2021-01-01"}), false);
|
||||
equal(assign.matchesProperties({"survey:date": "2021-03-29"}), false);
|
||||
equal(assign.matchesProperties({"_date:now": "2021-03-29"}), false);
|
||||
equal(assign.matchesProperties({"some_key": "2021-03-29"}), false);
|
||||
equal(false, t0.isEquivalent(t1))
|
||||
equal(false, t0.isEquivalent(t2))
|
||||
equal(false, t1.isEquivalent(t0))
|
||||
|
||||
})],
|
||||
["Is equivalent test", (() => {
|
||||
equal(false, t1.isEquivalent(t2))
|
||||
equal(false, t2.isEquivalent(t0))
|
||||
equal(false, t2.isEquivalent(t1))
|
||||
})],
|
||||
["Parse translation map", (() => {
|
||||
|
||||
const t0 = new And([
|
||||
new Tag("valves:special", "A"),
|
||||
new Tag("valves", "A")
|
||||
])
|
||||
const t1 = new And([
|
||||
new Tag("valves", "A")
|
||||
])
|
||||
const t2 = new And([
|
||||
new Tag("valves", "B")
|
||||
])
|
||||
equal(true, t0.isEquivalent(t0))
|
||||
equal(true, t1.isEquivalent(t1))
|
||||
equal(true, t2.isEquivalent(t2))
|
||||
const json: any = {"en": "English", "nl": "Nederlands"};
|
||||
const translation = Translations.WT(new Translation(json));
|
||||
Locale.language.setData("en");
|
||||
equal(translation.txt, "English");
|
||||
Locale.language.setData("nl");
|
||||
equal(translation.txt, "Nederlands");
|
||||
})],
|
||||
["Parse tag rendering", (() => {
|
||||
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",
|
||||
},
|
||||
|
||||
equal(false, t0.isEquivalent(t1))
|
||||
equal(false, t0.isEquivalent(t2))
|
||||
equal(false, t1.isEquivalent(t0))
|
||||
mappings: [
|
||||
{
|
||||
if: "noname=yes",
|
||||
"then": "Has no name"
|
||||
}
|
||||
],
|
||||
condition: "x="
|
||||
}, undefined, "");
|
||||
|
||||
equal(false, t1.isEquivalent(t2))
|
||||
equal(false, t2.isEquivalent(t0))
|
||||
equal(false, t2.isEquivalent(t1))
|
||||
})],
|
||||
["Parse translation map", (() => {
|
||||
equal(undefined, tr.GetRenderValue({"foo": "bar"}));
|
||||
equal("Has no name", tr.GetRenderValue({"noname": "yes"})?.txt);
|
||||
equal("Ook een {name}", tr.GetRenderValue({"name": "xyz"})?.txt);
|
||||
equal("Ook een xyz", SubstitutedTranslation.construct(tr.GetRenderValue({"name": "xyz"}),
|
||||
new UIEventSource<any>({"name": "xyz"})).InnerRender());
|
||||
equal(undefined, tr.GetRenderValue({"foo": "bar"}));
|
||||
|
||||
const json: any = {"en": "English", "nl": "Nederlands"};
|
||||
const translation = Translations.WT(new Translation(json));
|
||||
Locale.language.setData("en");
|
||||
equal(translation.txt, "English");
|
||||
Locale.language.setData("nl");
|
||||
equal(translation.txt, "Nederlands");
|
||||
})],
|
||||
["Parse tag rendering", (() => {
|
||||
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"
|
||||
[
|
||||
"Empty match test",
|
||||
() => {
|
||||
const t = new Tag("key", "");
|
||||
equal(false, t.matchesProperties({"key": "somevalue"}))
|
||||
}
|
||||
],
|
||||
condition: "x="
|
||||
}, undefined, "");
|
||||
[
|
||||
"Tagrendering test",
|
||||
() => {
|
||||
|
||||
equal(undefined, tr.GetRenderValue({"foo": "bar"}));
|
||||
equal("Has no name", tr.GetRenderValue({"noname": "yes"})?.txt);
|
||||
equal("Ook een {name}", tr.GetRenderValue({"name": "xyz"})?.txt);
|
||||
equal("Ook een xyz", SubstitutedTranslation.construct(tr.GetRenderValue({"name": "xyz"}),
|
||||
new UIEventSource<any>({"name": "xyz"})).InnerRender());
|
||||
equal(undefined, tr.GetRenderValue({"foo": "bar"}));
|
||||
const def = {
|
||||
"render": {
|
||||
"nl": "De toegankelijkheid van dit gebied is: {access:description}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Is dit gebied toegankelijk?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "access:description"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=",
|
||||
"leisure=park"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Dit gebied is vrij toegankelijk"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
},
|
||||
{
|
||||
"if": "access=no",
|
||||
"then": "Niet toegankelijk"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
})],
|
||||
const constr = new TagRenderingConfig(def, undefined, "test");
|
||||
const uiEl = new EditableTagRendering(new UIEventSource<any>(
|
||||
{leisure: "park", "access": "no"}), constr
|
||||
);
|
||||
const rendered = uiEl.InnerRender();
|
||||
equal(true, rendered.indexOf("Niet toegankelijk") > 0)
|
||||
|
||||
[
|
||||
"Empty match test",
|
||||
() => {
|
||||
const t = new Tag("key", "");
|
||||
equal(false, t.matchesProperties({"key": "somevalue"}))
|
||||
}
|
||||
],
|
||||
[
|
||||
"Tagrendering test",
|
||||
() => {
|
||||
}
|
||||
], [
|
||||
"Merge touching opening hours",
|
||||
() => {
|
||||
const oh1: OpeningHour = {
|
||||
weekday: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0,
|
||||
endHour: 11,
|
||||
endMinutes: 0
|
||||
};
|
||||
const oh0: OpeningHour = {
|
||||
weekday: 0,
|
||||
startHour: 11,
|
||||
startMinutes: 0,
|
||||
endHour: 12,
|
||||
endMinutes: 0
|
||||
};
|
||||
|
||||
const def = {
|
||||
"render": {
|
||||
"nl": "De toegankelijkheid van dit gebied is: {access:description}"
|
||||
},
|
||||
"question": {
|
||||
"nl": "Is dit gebied toegankelijk?"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "access:description"
|
||||
},
|
||||
"mappings": [
|
||||
const merged = OH.MergeTimes([oh0, oh1]);
|
||||
const r = merged[0];
|
||||
equal(merged.length, 1);
|
||||
equal(r.startHour, 10);
|
||||
equal(r.endHour, 12)
|
||||
|
||||
}
|
||||
], [
|
||||
"Merge overlapping opening hours",
|
||||
() => {
|
||||
const oh1: OpeningHour = {
|
||||
weekday: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0,
|
||||
endHour: 11,
|
||||
endMinutes: 0
|
||||
};
|
||||
const oh0: OpeningHour = {
|
||||
weekday: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 30,
|
||||
endHour: 12,
|
||||
endMinutes: 0
|
||||
};
|
||||
|
||||
const merged = OH.MergeTimes([oh0, oh1]);
|
||||
const r = merged[0];
|
||||
equal(merged.length, 1);
|
||||
equal(r.startHour, 10);
|
||||
equal(r.endHour, 12)
|
||||
|
||||
}],
|
||||
["Parse OH 1", () => {
|
||||
const rules = OH.ParseRule("11:00-19:00");
|
||||
equal(rules.length, 7);
|
||||
equal(rules[0].weekday, 0);
|
||||
equal(rules[0].startHour, 11);
|
||||
equal(rules[3].endHour, 19);
|
||||
|
||||
}],
|
||||
["Parse OH 2", () => {
|
||||
const rules = OH.ParseRule("Mo-Th 11:00-19:00");
|
||||
equal(rules.length, 4);
|
||||
equal(rules[0].weekday, 0);
|
||||
equal(rules[0].startHour, 11);
|
||||
equal(rules[3].endHour, 19);
|
||||
}],
|
||||
["JOIN OH 1", () => {
|
||||
const rules = OH.ToString([
|
||||
{
|
||||
"if": {
|
||||
"and": [
|
||||
"access:description=",
|
||||
"access=",
|
||||
"leisure=park"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"nl": "Dit gebied is vrij toegankelijk"
|
||||
},
|
||||
"hideInAnswer": true
|
||||
weekday: 0,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
{
|
||||
"if": "access=no",
|
||||
"then": "Niet toegankelijk"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const constr = new TagRenderingConfig(def, undefined, "test");
|
||||
const uiEl = new EditableTagRendering(new UIEventSource<any>(
|
||||
{leisure: "park", "access": "no"}), constr
|
||||
);
|
||||
const rendered = uiEl.InnerRender();
|
||||
equal(true, rendered.indexOf("Niet toegankelijk") > 0)
|
||||
|
||||
}
|
||||
], [
|
||||
"Merge touching opening hours",
|
||||
() => {
|
||||
const oh1: OpeningHour = {
|
||||
weekday: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0,
|
||||
endHour: 11,
|
||||
endMinutes: 0
|
||||
};
|
||||
const oh0: OpeningHour = {
|
||||
weekday: 0,
|
||||
startHour: 11,
|
||||
startMinutes: 0,
|
||||
endHour: 12,
|
||||
endMinutes: 0
|
||||
};
|
||||
|
||||
const merged = OH.MergeTimes([oh0, oh1]);
|
||||
const r = merged[0];
|
||||
equal(merged.length, 1);
|
||||
equal(r.startHour, 10);
|
||||
equal(r.endHour, 12)
|
||||
|
||||
}
|
||||
], [
|
||||
"Merge overlapping opening hours",
|
||||
() => {
|
||||
const oh1: OpeningHour = {
|
||||
weekday: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0,
|
||||
endHour: 11,
|
||||
endMinutes: 0
|
||||
};
|
||||
const oh0: OpeningHour = {
|
||||
weekday: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 30,
|
||||
endHour: 12,
|
||||
endMinutes: 0
|
||||
};
|
||||
|
||||
const merged = OH.MergeTimes([oh0, oh1]);
|
||||
const r = merged[0];
|
||||
equal(merged.length, 1);
|
||||
equal(r.startHour, 10);
|
||||
equal(r.endHour, 12)
|
||||
|
||||
}],
|
||||
["Parse OH 1", () => {
|
||||
const rules = OH.ParseRule("11:00-19:00");
|
||||
equal(rules.length, 7);
|
||||
equal(rules[0].weekday, 0);
|
||||
equal(rules[0].startHour, 11);
|
||||
equal(rules[3].endHour, 19);
|
||||
|
||||
}],
|
||||
["Parse OH 2", () => {
|
||||
const rules = OH.ParseRule("Mo-Th 11:00-19:00");
|
||||
equal(rules.length, 4);
|
||||
equal(rules[0].weekday, 0);
|
||||
equal(rules[0].startHour, 11);
|
||||
equal(rules[3].endHour, 19);
|
||||
}],
|
||||
["JOIN OH 1", () => {
|
||||
const rules = OH.ToString([
|
||||
{
|
||||
weekday: 0,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
{
|
||||
weekday: 0,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
},
|
||||
weekday: 0,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
weekday: 1,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
}, {
|
||||
weekday: 1,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
{
|
||||
weekday: 1,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
}, {
|
||||
weekday: 1,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
|
||||
]);
|
||||
equal(rules, "Mo-Tu 10:00-12:00, 13:00-17:00");
|
||||
}],
|
||||
["JOIN OH 2", () => {
|
||||
const rules = OH.ToString([
|
||||
]);
|
||||
equal(rules, "Mo-Tu 10:00-12:00, 13:00-17:00");
|
||||
}],
|
||||
["JOIN OH 2", () => {
|
||||
const rules = OH.ToString([
|
||||
|
||||
{
|
||||
weekday: 1,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
}, {
|
||||
weekday: 1,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
{
|
||||
weekday: 1,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
}, {
|
||||
weekday: 1,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
|
||||
]);
|
||||
equal(rules, "Tu 10:00-12:00, 13:00-17:00");
|
||||
}],
|
||||
["JOIN OH 3", () => {
|
||||
const rules = OH.ToString([
|
||||
]);
|
||||
equal(rules, "Tu 10:00-12:00, 13:00-17:00");
|
||||
}],
|
||||
["JOIN OH 3", () => {
|
||||
const rules = OH.ToString([
|
||||
|
||||
{
|
||||
weekday: 3,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
}, {
|
||||
weekday: 1,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
{
|
||||
weekday: 3,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
}, {
|
||||
weekday: 1,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
|
||||
]);
|
||||
equal(rules, "Tu 10:00-12:00; Th 13:00-17:00");
|
||||
}],
|
||||
["JOIN OH 3", () => {
|
||||
const rules = OH.ToString([
|
||||
]);
|
||||
equal(rules, "Tu 10:00-12:00; Th 13:00-17:00");
|
||||
}],
|
||||
["JOIN OH 3", () => {
|
||||
const rules = OH.ToString([
|
||||
|
||||
{
|
||||
weekday: 6,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
}, {
|
||||
weekday: 1,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
{
|
||||
weekday: 6,
|
||||
endHour: 17,
|
||||
endMinutes: 0,
|
||||
startHour: 13,
|
||||
startMinutes: 0
|
||||
}, {
|
||||
weekday: 1,
|
||||
endHour: 12,
|
||||
endMinutes: 0,
|
||||
startHour: 10,
|
||||
startMinutes: 0
|
||||
},
|
||||
|
||||
]);
|
||||
equal(rules, "Tu 10:00-12:00; Su 13:00-17:00");
|
||||
}],
|
||||
["OH 24/7", () => {
|
||||
const rules = OH.Parse("24/7");
|
||||
equal(rules.length, 7);
|
||||
equal(rules[0].startHour, 0);
|
||||
const asStr = OH.ToString(rules);
|
||||
equal(asStr, "24/7");
|
||||
}],
|
||||
["OH Th[-1] off", () => {
|
||||
const rules = OH.ParseRule("Th[-1] off");
|
||||
equal(rules, null);
|
||||
}],
|
||||
["OHNo parsePH 12:00-17:00", () => {
|
||||
const rules = OH.ParseRule("PH 12:00-17:00");
|
||||
equal(rules, null);
|
||||
}],
|
||||
["OH Parse PH 12:00-17:00", () => {
|
||||
const rules = PublicHolidayInput.LoadValue("PH 12:00-17:00");
|
||||
equal(rules.mode, " ");
|
||||
}],
|
||||
["Round", () => {
|
||||
equal(Utils.Round(15), "15.0")
|
||||
equal(Utils.Round(1), "1.0")
|
||||
equal(Utils.Round(1.5), "1.5")
|
||||
equal(Utils.Round(0.5), "0.5")
|
||||
equal(Utils.Round(1.6), "1.6")
|
||||
]);
|
||||
equal(rules, "Tu 10:00-12:00; Su 13:00-17:00");
|
||||
}],
|
||||
["OH 24/7", () => {
|
||||
const rules = OH.Parse("24/7");
|
||||
equal(rules.length, 7);
|
||||
equal(rules[0].startHour, 0);
|
||||
const asStr = OH.ToString(rules);
|
||||
equal(asStr, "24/7");
|
||||
}],
|
||||
["OH Th[-1] off", () => {
|
||||
const rules = OH.ParseRule("Th[-1] off");
|
||||
equal(rules, null);
|
||||
}],
|
||||
["OHNo parsePH 12:00-17:00", () => {
|
||||
const rules = OH.ParseRule("PH 12:00-17:00");
|
||||
equal(rules, null);
|
||||
}],
|
||||
["OH Parse PH 12:00-17:00", () => {
|
||||
const rules = PublicHolidayInput.LoadValue("PH 12:00-17:00");
|
||||
equal(rules.mode, " ");
|
||||
}],
|
||||
["Round", () => {
|
||||
equal(Utils.Round(15), "15.0")
|
||||
equal(Utils.Round(1), "1.0")
|
||||
equal(Utils.Round(1.5), "1.5")
|
||||
equal(Utils.Round(0.5), "0.5")
|
||||
equal(Utils.Round(1.6), "1.6")
|
||||
|
||||
equal(Utils.Round(-15), "-15.0")
|
||||
equal(Utils.Round(-1), "-1.0")
|
||||
equal(Utils.Round(-1.5), "-1.5")
|
||||
equal(Utils.Round(-0.5), "-0.5")
|
||||
equal(Utils.Round(-1.6), "-1.6")
|
||||
equal(Utils.Round(-15), "-15.0")
|
||||
equal(Utils.Round(-1), "-1.0")
|
||||
equal(Utils.Round(-1.5), "-1.5")
|
||||
equal(Utils.Round(-0.5), "-0.5")
|
||||
equal(Utils.Round(-1.6), "-1.6")
|
||||
|
||||
}
|
||||
],
|
||||
["Regression", () => {
|
||||
|
||||
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?"
|
||||
},
|
||||
"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=no",
|
||||
"then": {
|
||||
"en": "Water bottles may not fit",
|
||||
"nl": "Een drinkbus past moeilijk",
|
||||
"de": "Wasserflaschen passen möglicherweise nicht"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const tagRendering = new TagRenderingConfig(config, null, "test");
|
||||
equal(true, tagRendering.IsKnown({bottle: "yes"}))
|
||||
equal(false, tagRendering.IsKnown({}))
|
||||
}]]);
|
||||
}
|
||||
],
|
||||
["Regression", () => {
|
||||
|
||||
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?"
|
||||
},
|
||||
"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=no",
|
||||
"then": {
|
||||
"en": "Water bottles may not fit",
|
||||
"nl": "Een drinkbus past moeilijk",
|
||||
"de": "Wasserflaschen passen möglicherweise nicht"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const tagRendering = new TagRenderingConfig(config, null, "test");
|
||||
equal(true, tagRendering.IsKnown({bottle: "yes"}))
|
||||
equal(false, tagRendering.IsKnown({}))
|
||||
}]]);
|
||||
|
||||
}
|
||||
|
|
|
@ -7,53 +7,57 @@ import {UIEventSource} from "../Logic/UIEventSource";
|
|||
import TagRenderingConfig from "../Customizations/JSON/TagRenderingConfig";
|
||||
import EditableTagRendering from "../UI/Popup/EditableTagRendering";
|
||||
|
||||
|
||||
new T("TagQuestionElement",
|
||||
[
|
||||
["Freeform has textfield", () => {
|
||||
const tags = new UIEventSource({
|
||||
id: "way/123",
|
||||
amenity: 'public_bookcases'
|
||||
});
|
||||
const config = new TagRenderingConfig(
|
||||
{
|
||||
render: "The name is {name}",
|
||||
question: "What is the name of this bookcase?",
|
||||
freeform: {
|
||||
key: "name",
|
||||
type: "string"
|
||||
}
|
||||
}, undefined, "Testing tag"
|
||||
);
|
||||
const questionElement = new TagRenderingQuestion(tags, config);
|
||||
const html = questionElement.InnerRender();
|
||||
T.assertContains("What is the name of this bookcase?", html);
|
||||
T.assertContains("<input type='text'", html);
|
||||
}],
|
||||
["TagsQuestion with Freeform and mappings has textfield", () => {
|
||||
const tags = new UIEventSource({
|
||||
id: "way/123",
|
||||
amenity: 'public_bookcases'
|
||||
});
|
||||
const config = new TagRenderingConfig(
|
||||
{
|
||||
render: "The name is {name}",
|
||||
question: "What is the name of this bookcase?",
|
||||
freeform: {
|
||||
key: "name",
|
||||
type: "string"
|
||||
},
|
||||
mappings: [
|
||||
{"if": "noname=yes",
|
||||
"then": "This bookcase has no name"}
|
||||
]
|
||||
}, undefined, "Testing tag"
|
||||
);
|
||||
const questionElement = new TagRenderingQuestion(tags, config);
|
||||
const html = questionElement.InnerRender();
|
||||
T.assertContains("What is the name of this bookcase?", html);
|
||||
T.assertContains("This bookcase has no name", html);
|
||||
T.assertContains("<input type='text'", html);
|
||||
}]
|
||||
]
|
||||
);
|
||||
export default class TagQuestionSpec extends T {
|
||||
constructor() {
|
||||
super("TagQuestionElement",
|
||||
[
|
||||
["Freeform has textfield", () => {
|
||||
const tags = new UIEventSource({
|
||||
id: "way/123",
|
||||
amenity: 'public_bookcases'
|
||||
});
|
||||
const config = new TagRenderingConfig(
|
||||
{
|
||||
render: "The name is {name}",
|
||||
question: "What is the name of this bookcase?",
|
||||
freeform: {
|
||||
key: "name",
|
||||
type: "string"
|
||||
}
|
||||
}, undefined, "Testing tag"
|
||||
);
|
||||
const questionElement = new TagRenderingQuestion(tags, config);
|
||||
const html = questionElement.InnerRender();
|
||||
T.assertContains("What is the name of this bookcase?", html);
|
||||
T.assertContains("<input type='text'", html);
|
||||
}],
|
||||
["TagsQuestion with Freeform and mappings has textfield", () => {
|
||||
const tags = new UIEventSource({
|
||||
id: "way/123",
|
||||
amenity: 'public_bookcases'
|
||||
});
|
||||
const config = new TagRenderingConfig(
|
||||
{
|
||||
render: "The name is {name}",
|
||||
question: "What is the name of this bookcase?",
|
||||
freeform: {
|
||||
key: "name",
|
||||
type: "string"
|
||||
},
|
||||
mappings: [
|
||||
{
|
||||
"if": "noname=yes",
|
||||
"then": "This bookcase has no name"
|
||||
}
|
||||
]
|
||||
}, undefined, "Testing tag"
|
||||
);
|
||||
const questionElement = new TagRenderingQuestion(tags, config);
|
||||
const html = questionElement.InnerRender();
|
||||
T.assertContains("What is the name of this bookcase?", html);
|
||||
T.assertContains("This bookcase has no name", html);
|
||||
T.assertContains("<input type='text'", html);
|
||||
}]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
27
test/TestAll.ts
Normal file
27
test/TestAll.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import {Utils} from "../Utils";
|
||||
|
||||
Utils.runningFromConsole = true;
|
||||
|
||||
import TagSpec from "./Tag.spec";
|
||||
import ImageAttributionSpec from "./ImageAttribution.spec";
|
||||
import GeoOperationsSpec from "./GeoOperations.spec";
|
||||
import TagQuestionSpec from "./TagQuestion.spec";
|
||||
import ImageSearcherSpec from "./ImageSearcher.spec";
|
||||
import ThemeSpec from "./Theme.spec";
|
||||
import UtilsSpec from "./Utils.spec";
|
||||
|
||||
|
||||
const allTests = [
|
||||
new TagSpec(),
|
||||
new ImageAttributionSpec(),
|
||||
new GeoOperationsSpec(),
|
||||
new TagQuestionSpec(),
|
||||
new ImageSearcherSpec(),
|
||||
new ThemeSpec(),
|
||||
new UtilsSpec()]
|
||||
|
||||
for (const test of allTests) {
|
||||
if(test.failures.length > 0){
|
||||
throw "Some test failed"
|
||||
}
|
||||
}
|
|
@ -1,33 +1,38 @@
|
|||
|
||||
export default class T {
|
||||
|
||||
constructor(testsuite: string, tests: [string, () => void ][]) {
|
||||
let failures : string []= [];
|
||||
|
||||
public readonly failures = []
|
||||
|
||||
constructor(testsuite: string, tests: [string, () => void][]) {
|
||||
for (const [name, test] of tests) {
|
||||
try {
|
||||
test();
|
||||
} catch (e) {
|
||||
failures.push(name);
|
||||
this.failures.push(name);
|
||||
console.warn("Failed test: ", name, "because", e);
|
||||
}
|
||||
}
|
||||
if (failures.length == 0) {
|
||||
if (this.failures.length == 0) {
|
||||
console.log(`All tests of ${testsuite} done!`)
|
||||
} else {
|
||||
console.warn(failures.length, `tests of ${testsuite} failed :(`)
|
||||
console.log("Failed tests: ", failures.join(","))
|
||||
console.warn(this.failures.length, `tests of ${testsuite} failed :(`)
|
||||
console.log("Failed tests: ", this.failures.join(","))
|
||||
}
|
||||
}
|
||||
|
||||
static assertContains(needle: string, actual: string){
|
||||
if(actual.indexOf(needle) < 0){
|
||||
static assertContains(needle: string, actual: string) {
|
||||
if (actual.indexOf(needle) < 0) {
|
||||
throw `The substring ${needle} was not found`
|
||||
}
|
||||
}
|
||||
|
||||
static isTrue(b: boolean, msg: string) {
|
||||
if(!b){
|
||||
throw "Expected true, but got false: "+msg
|
||||
if (!b) {
|
||||
throw "Expected true, but got false: " + msg
|
||||
}
|
||||
}
|
||||
static isFalse(b: boolean, msg: string) {
|
||||
if (b) {
|
||||
throw "Expected false, but got true: " + msg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,40 +9,42 @@ import LayoutConfig from "../Customizations/JSON/LayoutConfig";
|
|||
import {LayoutConfigJson} from "../Customizations/JSON/LayoutConfigJson";
|
||||
import * as assert from "assert";
|
||||
|
||||
export default class ThemeSpec extends T{
|
||||
constructor() {
|
||||
super("Theme tests",
|
||||
[
|
||||
["Nested overrides work", () => {
|
||||
|
||||
new T("Theme tests",
|
||||
[
|
||||
["Nested overrides work", () => {
|
||||
|
||||
const themeConfigJson : LayoutConfigJson = {
|
||||
description: "Descr",
|
||||
icon: "",
|
||||
language: ["en"],
|
||||
layers: [
|
||||
{
|
||||
builtin: "public_bookcase",
|
||||
override: {
|
||||
source:{
|
||||
geoJson: "xyz"
|
||||
const themeConfigJson : LayoutConfigJson = {
|
||||
description: "Descr",
|
||||
icon: "",
|
||||
language: ["en"],
|
||||
layers: [
|
||||
{
|
||||
builtin: "public_bookcase",
|
||||
override: {
|
||||
source:{
|
||||
geoJson: "xyz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
maintainer: "",
|
||||
startLat: 0,
|
||||
startLon: 0,
|
||||
startZoom: 0,
|
||||
title: {
|
||||
en: "Title"
|
||||
},
|
||||
version: "",
|
||||
id: "test"
|
||||
}
|
||||
],
|
||||
maintainer: "",
|
||||
startLat: 0,
|
||||
startLon: 0,
|
||||
startZoom: 0,
|
||||
title: {
|
||||
en: "Title"
|
||||
},
|
||||
version: "",
|
||||
id: "test"
|
||||
}
|
||||
|
||||
const themeConfig = new LayoutConfig(themeConfigJson);
|
||||
assert.equal("xyz", themeConfig.layers[0].source.geojsonSource)
|
||||
|
||||
|
||||
}]
|
||||
]
|
||||
);
|
||||
|
||||
const themeConfig = new LayoutConfig(themeConfigJson);
|
||||
assert.equal("xyz", themeConfig.layers[0].source.geojsonSource)
|
||||
|
||||
|
||||
}]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,50 +1,84 @@
|
|||
import T from "./TestHelper";
|
||||
import {Utils} from "../Utils";
|
||||
import {equal} from "assert";
|
||||
import {existsSync, mkdirSync, readFileSync, writeFile, writeFileSync} from "fs";
|
||||
import LZString from "lz-string";
|
||||
new T("Utils",[
|
||||
["Minify-json",() => {
|
||||
const str = JSON.stringify({title: "abc", "and":"xyz", "render":"somevalue"}, null, 0);
|
||||
const minified = Utils.MinifyJSON(str);
|
||||
console.log(minified)
|
||||
console.log("Minified version has ", minified.length, "chars")
|
||||
const restored = Utils.UnMinify(minified)
|
||||
console.log(restored)
|
||||
console.log("Restored version has ", restored.length, "chars")
|
||||
equal(str, restored)
|
||||
|
||||
}],
|
||||
["Minify-json of the bookcases",() => {
|
||||
let str = readFileSync("/home/pietervdvn/git/MapComplete/assets/layers/public_bookcases/public_bookcases.json", "UTF8")
|
||||
str = JSON.stringify(JSON.parse(str), null, 0)
|
||||
const minified = Utils.MinifyJSON(str);
|
||||
console.log("Minified version has ", minified.length, "chars")
|
||||
const restored = Utils.UnMinify(minified)
|
||||
console.log("Restored version has ", restored.length, "chars")
|
||||
equal(str, restored)
|
||||
export default class UtilsSpec extends T {
|
||||
private static readonly 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"
|
||||
},
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
||||
}],
|
||||
["Minify-json with LZ-string of the bookcases",() => {
|
||||
let str = readFileSync("/home/pietervdvn/git/MapComplete/assets/layers/public_bookcases/public_bookcases.json", "UTF8")
|
||||
str = JSON.stringify(JSON.parse(str), null, 0)
|
||||
const minified =LZString.compressToBase64(Utils.MinifyJSON(str));
|
||||
console.log("Minified version has ", minified.length, "chars")
|
||||
const restored = Utils.UnMinify(LZString.decompressFromBase64(minified))
|
||||
console.log("Restored version has ", restored.length, "chars")
|
||||
equal(str, restored)
|
||||
constructor() {
|
||||
super("Utils", [
|
||||
["Minify-json", () => {
|
||||
const str = JSON.stringify({title: "abc", "and": "xyz", "render": "somevalue"}, null, 0);
|
||||
const minified = Utils.MinifyJSON(str);
|
||||
console.log(minified)
|
||||
console.log("Minified version has ", minified.length, "chars")
|
||||
const restored = Utils.UnMinify(minified)
|
||||
console.log(restored)
|
||||
console.log("Restored version has ", restored.length, "chars")
|
||||
equal(str, restored)
|
||||
|
||||
}],
|
||||
["Minify-json with only LZ-string of the bookcases",() => {
|
||||
let str = readFileSync("/home/pietervdvn/git/MapComplete/assets/layers/public_bookcases/public_bookcases.json", "UTF8")
|
||||
str = JSON.stringify(JSON.parse(str), null, 0)
|
||||
const minified =LZString.compressToBase64(str);
|
||||
console.log("Minified version has ", minified.length, "chars")
|
||||
const restored = LZString.decompressFromBase64(minified)
|
||||
console.log("Restored version has ", restored.length, "chars")
|
||||
equal(str, restored)
|
||||
}],
|
||||
["Minify-json of the bookcases", () => {
|
||||
const str = JSON.stringify(UtilsSpec.example, null, 0)
|
||||
const minified = Utils.MinifyJSON(str);
|
||||
console.log("Minified version has ", minified.length, "chars")
|
||||
const restored = Utils.UnMinify(minified)
|
||||
console.log("Restored version has ", restored.length, "chars")
|
||||
equal(str, restored)
|
||||
|
||||
}]
|
||||
|
||||
|
||||
])
|
||||
}],
|
||||
["Minify-json with LZ-string of the bookcases", () => {
|
||||
const str = JSON.stringify(UtilsSpec.example, null, 0)
|
||||
const minified = LZString.compressToBase64(Utils.MinifyJSON(str));
|
||||
console.log("Minified version has ", minified.length, "chars")
|
||||
const restored = Utils.UnMinify(LZString.decompressFromBase64(minified))
|
||||
console.log("Restored version has ", restored.length, "chars")
|
||||
equal(str, restored)
|
||||
|
||||
}],
|
||||
["Minify-json with only LZ-string of the bookcases", () => {
|
||||
const str = JSON.stringify(UtilsSpec.example, null, 0)
|
||||
const minified = LZString.compressToBase64(str);
|
||||
console.log("Minified version has ", minified.length, "chars")
|
||||
const restored = LZString.decompressFromBase64(minified)
|
||||
console.log("Restored version has ", restored.length, "chars")
|
||||
equal(str, restored)
|
||||
|
||||
}]
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue