📝 Remplace & applicable: split getApplicableReplacements & tests

* Split and document `getApplicableReplacements`
* More remplace tests
* `isDisabledBy` is mandatory in `ParsedRule`
pull/1136/head
Alexandre Hajjar 2020-10-08 11:21:50 +02:00
parent 94c653678a
commit 960fda08e6
3 changed files with 81 additions and 18 deletions

View File

@ -9,6 +9,32 @@ import { disambiguateRuleReference } from './ruleUtils'
import { EvaluatedNode, ParsedRule } from './types'
import { areUnitConvertible, serializeUnit } from './units'
/**
* Statically filter out replacements from `replaceBy`.
* Note: whitelist and blacklist filtering are applicable to the replacement
* itself or any parent namespace.
*/
export const getApplicableReplacedBy = (contextRuleName, replacedBy) =>
replacedBy
.sort(
(replacement1, replacement2) =>
+!!replacement2.whiteListedNames - +!!replacement1.whiteListedNames
)
.filter(
({ whiteListedNames }) =>
!whiteListedNames ||
whiteListedNames.some(name => contextRuleName.startsWith(name))
)
.filter(
({ blackListedNames }) =>
!blackListedNames ||
blackListedNames.every(name => !contextRuleName.startsWith(name))
)
.filter(({ referenceNode }) => contextRuleName !== referenceNode.dottedName)
/**
* Filter-out and apply all possible replacements at runtime.
*/
const getApplicableReplacements = (
filter,
contextRuleName,
@ -21,23 +47,10 @@ const getApplicableReplacements = (
if (contextRuleName.startsWith('[evaluation]')) {
return [[], []]
}
const applicableReplacements = rule.replacedBy
.sort(
(replacement1, replacement2) =>
+!!replacement2.whiteListedNames - +!!replacement1.whiteListedNames
)
// Remove remplacement not in whitelist
.filter(
({ whiteListedNames }) =>
!whiteListedNames ||
whiteListedNames.some(name => contextRuleName.startsWith(name))
)
.filter(
({ blackListedNames }) =>
!blackListedNames ||
blackListedNames.every(name => !contextRuleName.startsWith(name))
)
.filter(({ referenceNode }) => contextRuleName !== referenceNode.dottedName)
const applicableReplacements = getApplicableReplacedBy(
contextRuleName,
rule.replacedBy
)
// Remove remplacement defined in a not applicable node
.filter(({ referenceNode }) => {
const referenceRule = rules[referenceNode.dottedName]

View File

@ -39,7 +39,7 @@ export type ParsedRule<Name extends string = string> = Rule & {
formule?: any
evaluate?: () => EvaluatedRule<Name>
explanation?: any
isDisabledBy?: Array<any>
isDisabledBy: Array<any>
replacedBy: Array<{
whiteListedNames: Array<Name>
blackListedNames: Array<Name>

View File

@ -181,3 +181,53 @@ remplacement non applicable car branche desactivée:
formule: z
exemples:
- valeur attendue: 1
# Remplacement non effectué dans la formule du remplacement
espace . valeur:
formule: 20
espace . remplacement:
remplace: valeur
formule: valeur + 10
test remplacement non effectué dans la formule du remplacement:
formule: espace . valeur
exemples:
- valeur attendue: 30
frais de repas:
formule: 5 €/repas
convention hôtels cafés restaurants:
formule: oui
convention hôtels cafés restaurants . frais de repas:
remplace: frais de repas
formule: 6 €/repas
frais de repas non remplacé:
formule: frais de repas
exemples:
- valeur attendue: 5
# Note: this would produce an infinite loop
# frais de repas remplacé:
# formule: convention hôtels cafés restaurants . frais de repas
# exemples:
# - nom: par défaut
# valeur attendue: 5
frais de repas2:
formule: 5 €/repas
convention hôtels cafés restaurants2:
formule: oui
convention hôtels cafés restaurants2 . remplaçeur:
remplace: frais de repas2
formule: 6 €/repas
frais de repas2 remplacé:
formule: frais de repas2
exemples:
- valeur attendue: 6