237 lines
6.1 KiB
JavaScript
237 lines
6.1 KiB
JavaScript
import { expect } from 'chai'
|
|
import dedent from 'dedent-js'
|
|
import yaml from 'js-yaml'
|
|
import { collectMissingVariables } from '../source/engine/generateQuestions'
|
|
import { enrichRule, rules as realRules } from '../source/engine/rules'
|
|
import { analyse, analyseMany, parseAll } from '../source/engine/traverse'
|
|
|
|
describe('inversions', () => {
|
|
it('should handle non inverted example', () => {
|
|
let fakeState = { brut: 2300 }
|
|
let stateSelector = name => fakeState[name]
|
|
|
|
let rawRules = dedent`
|
|
- nom: net
|
|
formule:
|
|
multiplication:
|
|
assiette: brut
|
|
taux: 77%
|
|
|
|
- nom: brut
|
|
format: euro
|
|
`,
|
|
rules = parseAll(yaml.safeLoad(rawRules).map(enrichRule)),
|
|
analysis = analyse(rules, 'net')(stateSelector)
|
|
|
|
expect(analysis.targets[0].nodeValue).to.be.closeTo(1771, 0.001)
|
|
})
|
|
|
|
it('should handle simple inversion', () => {
|
|
let fakeState = { net: 2000 }
|
|
let stateSelector = name => fakeState[name]
|
|
|
|
let rawRules = dedent`
|
|
- nom: net
|
|
formule:
|
|
multiplication:
|
|
assiette: brut
|
|
taux: 77%
|
|
|
|
- nom: brut
|
|
format: euro
|
|
formule:
|
|
inversion:
|
|
avec:
|
|
- net
|
|
`,
|
|
rules = parseAll(yaml.safeLoad(rawRules).map(enrichRule)),
|
|
analysis = analyse(rules, 'brut')(stateSelector)
|
|
|
|
expect(analysis.targets[0].nodeValue).to.be.closeTo(
|
|
2000 / (77 / 100),
|
|
0.0001 * 2000
|
|
)
|
|
})
|
|
|
|
it('should ask the input of one of the possible inversions', () => {
|
|
let rawRules = dedent`
|
|
- nom: net
|
|
formule:
|
|
multiplication:
|
|
assiette: assiette
|
|
variations:
|
|
- si: cadre
|
|
alors:
|
|
taux: 80%
|
|
- sinon:
|
|
taux: 70%
|
|
|
|
- nom: brut
|
|
format: euro
|
|
formule:
|
|
inversion:
|
|
avec:
|
|
- net
|
|
- nom: cadre
|
|
- nom: assiette
|
|
formule: 67 + brut
|
|
|
|
`,
|
|
rules = parseAll(yaml.safeLoad(rawRules).map(enrichRule)),
|
|
stateSelector = () => null,
|
|
analysis = analyse(rules, 'brut')(stateSelector),
|
|
missing = collectMissingVariables(analysis.targets)
|
|
|
|
expect(analysis.targets[0].nodeValue).to.be.null
|
|
expect(missing).to.include('brut')
|
|
})
|
|
|
|
it('should handle inversions with missing variables', () => {
|
|
let rawRules = dedent`
|
|
- nom: net
|
|
formule:
|
|
multiplication:
|
|
assiette: assiette
|
|
variations:
|
|
- si: cadre
|
|
alors:
|
|
taux: 80%
|
|
- sinon:
|
|
taux: 70%
|
|
|
|
- nom: brut
|
|
format: euro
|
|
formule:
|
|
inversion:
|
|
avec:
|
|
- net
|
|
- nom: cadre
|
|
- nom: assiette
|
|
formule:
|
|
somme:
|
|
- 1200
|
|
- brut
|
|
- taxeOne
|
|
- nom: taxeOne
|
|
non applicable si: cadre
|
|
formule: taxe + taxe
|
|
- nom: taxe
|
|
formule:
|
|
multiplication:
|
|
assiette: 1200
|
|
variations:
|
|
- si: cadre
|
|
alors:
|
|
taux: 80%
|
|
- sinon:
|
|
taux: 70%
|
|
`,
|
|
rules = parseAll(yaml.safeLoad(rawRules).map(enrichRule)),
|
|
stateSelector = name => ({ net: 2000 }[name]),
|
|
analysis = analyse(rules, 'brut')(stateSelector),
|
|
missing = collectMissingVariables(analysis.targets)
|
|
|
|
expect(analysis.targets[0].nodeValue).to.be.null
|
|
expect(missing).to.include('cadre')
|
|
})
|
|
|
|
it("shouldn't report a missing salary if another salary was input", () => {
|
|
let rawRules = dedent`
|
|
- nom: net
|
|
formule:
|
|
multiplication:
|
|
assiette: assiette
|
|
variations:
|
|
- si: cadre
|
|
alors:
|
|
taux: 80%
|
|
- si: ≠ cadre
|
|
alors:
|
|
taux: 70%
|
|
|
|
- nom: total
|
|
formule:
|
|
multiplication:
|
|
assiette: assiette
|
|
taux: 150%
|
|
|
|
- nom: brut
|
|
format: euro
|
|
formule:
|
|
inversion:
|
|
avec:
|
|
- net
|
|
- total
|
|
|
|
- nom: cadre
|
|
|
|
- nom: assiette
|
|
formule: 67 + brut
|
|
|
|
`,
|
|
rules = parseAll(yaml.safeLoad(rawRules).map(enrichRule)),
|
|
stateSelector = name => ({ net: 2000, cadre: 'oui' }[name]),
|
|
analysis = analyse(rules, 'total')(stateSelector),
|
|
missing = collectMissingVariables(analysis.targets)
|
|
|
|
expect(analysis.targets[0].nodeValue).to.equal(3750)
|
|
expect(missing).to.be.empty
|
|
})
|
|
})
|
|
|
|
it('complex inversion with composantes', () => {
|
|
let rawRules = dedent`
|
|
- nom: net
|
|
formule:
|
|
multiplication:
|
|
assiette: 67 + brut
|
|
taux: 80%
|
|
|
|
- nom: cotisation
|
|
formule:
|
|
multiplication:
|
|
assiette: 67 + brut
|
|
composantes:
|
|
- attributs:
|
|
dû par: employeur
|
|
taux: 100%
|
|
- attributs:
|
|
dû par: salarié
|
|
taux: 50%
|
|
|
|
- nom: total
|
|
formule: cotisation (employeur) + cotisation (salarié)
|
|
|
|
- nom: brut
|
|
format: euro
|
|
formule:
|
|
inversion:
|
|
avec:
|
|
- net
|
|
- total
|
|
`,
|
|
rules = parseAll(yaml.safeLoad(rawRules).map(enrichRule)),
|
|
stateSelector = name => ({ net: 2000 }[name]),
|
|
analysis = analyse(rules, 'total')(stateSelector),
|
|
missing = collectMissingVariables(analysis.targets)
|
|
|
|
expect(analysis.targets[0].nodeValue).to.equal(3750)
|
|
expect(missing).to.be.empty
|
|
})
|
|
|
|
it('should collect missing variables not too slowly', function() {
|
|
let stateSelector = name =>
|
|
({ 'contrat salarié . salaire . net': '2300' }[name])
|
|
|
|
let rules = parseAll(realRules.map(enrichRule)),
|
|
analysis = analyseMany(rules, [
|
|
'contrat salarié . salaire . brut',
|
|
'contrat salarié . rémunération . total'
|
|
])(stateSelector)
|
|
|
|
let start = Date.now()
|
|
collectMissingVariables(analysis.targets)
|
|
let elapsed = Date.now() - start
|
|
expect(elapsed).to.be.below(500)
|
|
})
|