More test cleanup

This commit is contained in:
pietervdvn 2022-03-21 02:00:50 +01:00
parent b67e108056
commit 3ab373f6ec
9 changed files with 179 additions and 370 deletions

View file

@ -32,6 +32,32 @@ export class OH {
return Utils.TwoDigits(h) + ":" + Utils.TwoDigits(m); return Utils.TwoDigits(h) + ":" + Utils.TwoDigits(m);
} }
/**
* const rules = [{weekday: 6,endHour: 17,endMinutes: 0,startHour: 13,startMinutes: 0},
* {weekday: 1,endHour: 12,endMinutes: 0,startHour: 10,startMinutes: 0}]
* OH.ToString(rules) // => "Tu 10:00-12:00; Su 13:00-17:00"
*
* const rules = [{weekday: 3,endHour: 17,endMinutes: 0,startHour: 13,startMinutes: 0}, {weekday: 1,endHour: 12,endMinutes: 0,startHour: 10,startMinutes: 0}]
* OH.ToString(rules) // => "Tu 10:00-12:00; Th 13:00-17:00"
*
* const rules = [ { weekday: 1, endHour: 17, endMinutes: 0, startHour: 13, startMinutes: 0 }, { weekday: 1, endHour: 12, endMinutes: 0, startHour: 10, startMinutes: 0 }]);
* OH.ToString(rules) // => "Tu 10:00-12:00, 13:00-17:00"
*
* const rules = [ { weekday: 0, endHour: 12, endMinutes: 0, startHour: 10, 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 }];
* OH.ToString(rules) // => "Mo-Tu 10:00-12:00, 13:00-17:00"
*
* // should merge overlapping opening hours
* const timerange0 = {weekday: 1, endHour: 23, endMinutes: 30, startHour: 23, startMinutes: 0 }
* const touchingTimeRange = { weekday: 1, endHour: 0, endMinutes: 0, startHour: 23, startMinutes: 30 }
* OH.ToString(OH.MergeTimes([timerange0, touchingTimeRange])) // => "Tu 23:00-00:00"
*
* // should merge touching opening hours
* const timerange0 = {weekday: 1, endHour: 23, endMinutes: 30, startHour: 23, startMinutes: 0 }
* const overlappingTimeRange = { weekday: 1, endHour: 24, endMinutes: 0, startHour: 23, startMinutes: 30 }
* OH.ToString(OH.MergeTimes([timerange0, overlappingTimeRange])) // => "Tu 23:00-00:00"
*
*/
public static ToString(ohs: OpeningHour[]) { public static ToString(ohs: OpeningHour[]) {
if (ohs.length == 0) { if (ohs.length == 0) {
return ""; return "";
@ -86,8 +112,16 @@ export class OH {
/** /**
* Merge duplicate opening-hour element in place. * Merge duplicate opening-hour element in place.
* Returns true if something changed * Returns true if something changed
* @param ohs *
* @constructor * // should 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 };
* OH.MergeTimes([oh0, oh1]) // => [{ weekday: 0, startHour: 10, startMinutes: 0, endHour: 12, endMinutes: 0 }]
*
* // should 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 };
* OH.MergeTimes([oh0, oh1]) // => [{ weekday: 0, startHour: 10, startMinutes: 0, endHour: 12, endMinutes: 0 }]
*/ */
public static MergeTimes(ohs: OpeningHour[]): OpeningHour[] { public static MergeTimes(ohs: OpeningHour[]): OpeningHour[] {
const queue = ohs.map(oh => { const queue = ohs.map(oh => {
@ -248,6 +282,7 @@ export class OH {
* rules[0].weekday // => 0 * rules[0].weekday // => 0
* rules[0].startHour // => 11 * rules[0].startHour // => 11
* rules[3].endHour // => 19 * rules[3].endHour // => 19
*
*/ */
public static ParseRule(rule: string): OpeningHour[] { public static ParseRule(rule: string): OpeningHour[] {
try { try {

View file

@ -209,6 +209,13 @@ export class Translation extends BaseUIElement {
return new Translation(tr); return new Translation(tr);
} }
/**
* Extracts all images (including HTML-images) from all the embedded translations
*
* // should detect sources of <img>
* const tr = new Translation({en: "XYZ <img src='a.svg'/> XYZ <img src=\"some image.svg\"></img> XYZ <img src=b.svg/>"})
* new Set<string>(tr.ExtractImages(false)) // new Set(["a.svg", "b.svg", "some image.svg"])
*/
public ExtractImages(isIcon = false): string[] { public ExtractImages(isIcon = false): string[] {
const allIcons: string[] = [] const allIcons: string[] = []
for (const key in this.translations) { for (const key in this.translations) {

View file

@ -1,45 +0,0 @@
import {equal} from "assert";
import T from "./TestHelper";
import {Translation} from "../UI/i18n/Translation";
import * as cyclofix from "../assets/generated/themes/cyclofix.json"
import {ExtractImages} from "../Models/ThemeConfig/Conversion/FixImages";
export default class ImageAttributionSpec extends T {
constructor() {
super([
[
"Should find all the images",
() => {
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) {
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")
}
]
]);
}
}

View file

@ -1,297 +0,0 @@
import {equal} from "assert";
import T from "./TestHelper";
import Locale from "../UI/i18n/Locale";
import {OH, OpeningHour} from "../UI/OpeningHours/OpeningHours";
import {Tag} from "../Logic/Tags/Tag";
import {And} from "../Logic/Tags/And";
import {TagUtils} from "../Logic/Tags/TagUtils";
import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig";
import {RegexTag} from "../Logic/Tags/RegexTag";
export default class TagSpec extends T {
constructor() {
super([
["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"
}
],
condition: "x="
}, "Tests");
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(undefined, tr.GetRenderValue({"foo": "bar"}));
})],
[
"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)
}],
["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: 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([
{
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([
{
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([
{
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");
}],
["JOIN OH with end hours", () => {
const rules = OH.ToString(
OH.MergeTimes([
{
weekday: 1,
endHour: 23,
endMinutes: 30,
startHour: 23,
startMinutes: 0
}, {
weekday: 1,
endHour: 24,
endMinutes: 0,
startHour: 23,
startMinutes: 30
},
]));
equal(rules, "Tu 23:00-00:00");
}],
["JOIN OH with overflowed hours", () => {
const rules = OH.ToString(
OH.MergeTimes([
{
weekday: 1,
endHour: 23,
endMinutes: 30,
startHour: 23,
startMinutes: 0
}, {
weekday: 1,
endHour: 0,
endMinutes: 0,
startHour: 23,
startMinutes: 30
},
]));
equal(rules, "Tu 23:00-00:00");
}],
["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, "test");
equal(true, tagRendering.IsKnown({bottle: "yes"}))
equal(false, tagRendering.IsKnown({}))
}],
[
"Tag matches a lazy property",
() => {
const properties = {}
const key = "_key"
Object.defineProperty(properties, key, {
configurable: true,
get: function () {
delete properties[key]
properties[key] = "yes"
return "yes"
}
})
const filter = new Tag("_key", "yes")
T.isTrue(filter.matchesProperties(properties), "Lazy value not matched")
}
],
[
"RegextTag matches a lazy property",
() => {
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~*")
T.isTrue(filter.matchesProperties(properties), "Lazy value not matched")
}
]]);
}
}

View file

@ -1,50 +1,32 @@
import TagSpec from "./Tag.spec";
import ImageAttributionSpec from "./ImageAttribution.spec";
import GeoOperationsSpec from "./GeoOperations.spec"; import GeoOperationsSpec from "./GeoOperations.spec";
import ThemeSpec from "./Theme.spec";
import UtilsSpec from "./Utils.spec";
import OsmObjectSpec from "./OsmObject.spec"; import OsmObjectSpec from "./OsmObject.spec";
import ScriptUtils from "../scripts/ScriptUtils"; import ScriptUtils from "../scripts/ScriptUtils";
import UnitsSpec from "./Units.spec";
import RelationSplitHandlerSpec from "./RelationSplitHandler.spec"; import RelationSplitHandlerSpec from "./RelationSplitHandler.spec";
import SplitActionSpec from "./SplitAction.spec"; import SplitActionSpec from "./SplitAction.spec";
import {Utils} from "../Utils"; import {Utils} from "../Utils";
import TileFreshnessCalculatorSpec from "./TileFreshnessCalculator.spec";
import ImageProviderSpec from "./ImageProvider.spec"; import ImageProviderSpec from "./ImageProvider.spec";
import ActorsSpec from "./Actors.spec";
import ReplaceGeometrySpec from "./ReplaceGeometry.spec"; import ReplaceGeometrySpec from "./ReplaceGeometry.spec";
import LegacyThemeLoaderSpec from "./LegacyThemeLoader.spec"; import LegacyThemeLoaderSpec from "./LegacyThemeLoader.spec";
import T from "./TestHelper"; import T from "./TestHelper";
import CreateNoteImportLayerSpec from "./CreateNoteImportLayer.spec"; import CreateNoteImportLayerSpec from "./CreateNoteImportLayer.spec";
import CreateCacheSpec from "./CreateCache.spec"; import CreateCacheSpec from "./CreateCache.spec";
import CodeQualitySpec from "./CodeQuality.spec";
import ImportMultiPolygonSpec from "./ImportMultiPolygon.spec"; import ImportMultiPolygonSpec from "./ImportMultiPolygon.spec";
import ChangesetHandlerSpec from "./ChangesetHandler.spec"; import ChangesetHandlerSpec from "./ChangesetHandler.spec";
import ChangesSpec from "./Changes.spec";
async function main() { async function main() {
const allTests: T[] = [ const allTests: T[] = [
new ChangesSpec(),
new ChangesetHandlerSpec(), new ChangesetHandlerSpec(),
new OsmObjectSpec(), new OsmObjectSpec(),
new TagSpec(),
new ImageAttributionSpec(),
new GeoOperationsSpec(), new GeoOperationsSpec(),
new ThemeSpec(),
new UtilsSpec(),
new UnitsSpec(),
new RelationSplitHandlerSpec(), new RelationSplitHandlerSpec(),
new SplitActionSpec(), new SplitActionSpec(),
new TileFreshnessCalculatorSpec(),
new ImageProviderSpec(), new ImageProviderSpec(),
new ActorsSpec(),
new ReplaceGeometrySpec(), new ReplaceGeometrySpec(),
new LegacyThemeLoaderSpec(), new LegacyThemeLoaderSpec(),
new CreateNoteImportLayerSpec(), new CreateNoteImportLayerSpec(),
new CreateCacheSpec(), new CreateCacheSpec(),
new CodeQualitySpec(),
new ImportMultiPolygonSpec(), new ImportMultiPolygonSpec(),
] ]
ScriptUtils.fixUtils(); ScriptUtils.fixUtils();

View file

@ -8,12 +8,6 @@ export default class T {
this._tests = tests; this._tests = tests;
} }
static assertContains(needle: string, actual: string) {
if (actual.indexOf(needle) < 0) {
throw `The substring ${needle} was not found`
}
}
static isTrue(b: boolean, msg: string) { static isTrue(b: boolean, msg: string) {
if (!b) { if (!b) {
throw "Expected true, but got false: " + msg throw "Expected true, but got false: " + msg

View file

@ -0,0 +1,41 @@
import {describe} from 'mocha'
import {expect} from 'chai'
import {TagUtils} from "../../../Logic/Tags/TagUtils";
import T from "../../../testLegacy/TestHelper";
import {Tag} from "../../../Logic/Tags/Tag";
describe("Lazy object properties", () => {
it("should be matche by a normal tag", () => {
const properties = {}
const key = "_key"
Object.defineProperty(properties, key, {
configurable: true,
get: function () {
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;
})
})

View file

@ -1,14 +1,14 @@
import {describe} from 'mocha' import {describe} from 'mocha'
import {expect} from 'chai' import {expect} from 'chai'
import {LayoutConfigJson} from "../../../../Models/ThemeConfig/Json/LayoutConfigJson"; import {LayoutConfigJson} from "../../../../Models/ThemeConfig/Json/LayoutConfigJson";
import Constants from "../../../../Models/Constants";
import {LayerConfigJson} from "../../../../Models/ThemeConfig/Json/LayerConfigJson"; import {LayerConfigJson} from "../../../../Models/ThemeConfig/Json/LayerConfigJson";
import {PrepareTheme} from "../../../../Models/ThemeConfig/Conversion/PrepareTheme"; import {PrepareTheme} from "../../../../Models/ThemeConfig/Conversion/PrepareTheme";
import {TagRenderingConfigJson} from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson"; import {TagRenderingConfigJson} from "../../../../Models/ThemeConfig/Json/TagRenderingConfigJson";
import LayoutConfig from "../../../../Models/ThemeConfig/LayoutConfig"; import LayoutConfig from "../../../../Models/ThemeConfig/LayoutConfig";
import assert from "assert";
import * as bookcaseLayer from "../../../../assets/generated/layers/public_bookcase.json" import * as bookcaseLayer from "../../../../assets/generated/layers/public_bookcase.json"
import LayerConfig from "../../../../Models/ThemeConfig/LayerConfig"; import LayerConfig from "../../../../Models/ThemeConfig/LayerConfig";
import {ExtractImages} from "../../../../Models/ThemeConfig/Conversion/FixImages";
import * as cyclofix from "../../../../assets/generated/themes/cyclofix.json"
const themeConfigJson: LayoutConfigJson = { const themeConfigJson: LayoutConfigJson = {
@ -52,3 +52,24 @@ describe("PrepareTheme", () => {
}) })
}) })
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)
}
})
})

View file

@ -0,0 +1,71 @@
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",
},
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
})
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?"
},
"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, "test");
expect(tagRendering.IsKnown({bottle: "yes"})).true
expect(tagRendering.IsKnown({})).false
})
})
})