Add more docs, add more checks, add more tests

This commit is contained in:
Pieter Vander Vennet 2021-03-14 01:40:35 +01:00
parent a50b9fba59
commit 2c3c110624
7 changed files with 162 additions and 13 deletions

View file

@ -82,8 +82,11 @@ export default class TagRenderingConfig {
this.multiAnswer = json.multiAnswer ?? false
if (json.mappings) {
this.mappings = json.mappings.map((mapping, i) => {
if (mapping.then === undefined) {
throw `${context}.mapping[${i}]: Invalid mapping: if without body`
}
@ -104,7 +107,7 @@ export default class TagRenderingConfig {
hideInAnswer: hideInAnswer
};
if (this.question) {
if (hideInAnswer !== true && !mp.if.isUsableAsAnswer()) {
if (hideInAnswer !== true && mp.if !== undefined && !mp.if.isUsableAsAnswer()) {
throw `${context}.mapping[${i}].if: This value cannot be used to answer a question, probably because it contains a regex or an OR. Either change it or set 'hideInAnswer'`
}
@ -128,6 +131,32 @@ export default class TagRenderingConfig {
if(this.render && this.question && this.freeform === undefined){
throw `${context}: Detected a tagrendering which takes input without freeform key in ${context}`
}
if(!json.multiAnswer && this.mappings !== undefined && this.question !== undefined){
let keys = []
for (let i = 0; i < this.mappings.length; i++){
const mapping = this.mappings[i];
if(mapping.if === undefined){
throw `${context}.mappings[${i}].if is undefined`
}
keys.push(...mapping.if.usedKeys())
}
keys = Utils.Dedup(keys)
for (let i = 0; i < this.mappings.length; i++){
const mapping = this.mappings[i];
if(mapping.hideInAnswer){
continue
}
const usedKeys = mapping.if.usedKeys();
for (const expectedKey of keys) {
if(usedKeys.indexOf(expectedKey) < 0){
const msg = `${context}.mappings[${i}]: This mapping only defines values for ${usedKeys.join(', ')}, but it should also give a value for ${expectedKey}`
console.warn(msg)
}
}
}
}
if (this.question !== undefined && json.multiAnswer) {
if ((this.mappings?.length ?? 0) === 0) {

View file

@ -49,14 +49,64 @@ export interface TagRenderingConfigJson {
* Allows fixed-tag inputs, shown either as radiobuttons or as checkboxes
*/
mappings?: {
/**
* If this condition is met, then the text under `then` will be shown.
* If no value matches, and the user selects this mapping as an option, then these tags will be uploaded to OSM.
*/
if: AndOrTagConfigJson | string,
/**
* Only applicable if 'multiAnswer' is set.
* This tag is applied if the respective checkbox is unset
* If the condition `if` is met, the text `then` will be rendered.
* If not known yet, the user will be presented with `then` as an option
*/
ifnot?: AndOrTagConfigJson | string,
then: string | any
hideInAnswer?: boolean
then: string | any,
/**
* In some cases, multiple taggings exist (e.g. a default assumption, or a commonly mapped abbreviation and a fully written variation).
*
* In the latter case, a correct text should be shown, but only a single, canonical tagging should be selectable by the user.
* In this case, one of the mappings can be hiden by setting this flag.
*
* To demonstrate an example making a default assumption:
*
* mappings: [
* {
* if: "access=", -- no access tag present, we assume accessible
* then: "Accessible to the general public",
* hideInAnswer: true
* },
* {
* if: "access=yes",
* then: "Accessible to the general public", -- the user selected this, we add that to OSM
* },
* {
* if: "access=no",
* then: "Not accessible to the public"
* }
* ]
*
*
* For example, for an operator, we have `operator=Agentschap Natuur en Bos`, which is often abbreviated to `operator=ANB`.
* Then, we would add two mappings:
* {
* if: "operator=Agentschap Natuur en Bos" -- the non-abbreviated version which should be uploaded
* then: "Maintained by Agentschap Natuur en Bos"
* },
* {
* if: "operator=ANB", -- we don't want to upload abbreviations
* then: "Maintained by Agentschap Natuur en Bos"
* hideInAnswer: true
* }
*/
hideInAnswer?: boolean,
/**
* Only applicable if 'multiAnswer' is set.
* This is for situations such as:
* `accepts:coins=no` where one can select all the possible payment methods. However, we want to make explicit that some options _were not_ selected.
* This can be done with `ifnot`
* Note that we can not explicitly render this negative case to the user, we cannot show `does _not_ accept coins`.
* If this is important to your usecase, consider using multiple radiobutton-fields without `multiAnswer`
*/
ifnot?: AndOrTagConfigJson | string
}[]
/**