import { expect } from "chai" import { rules as realRules, enrichRule } from '../source/engine/rules' import { analyse, analyseMany, parseAll } from "../source/engine/traverse" import { collectMissingVariables } from "../source/engine/generateQuestions" import yaml from "js-yaml" import dedent from "dedent-js" 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 taux: 80% - si: ≠ cadre 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 = name => null, analysis = analyse(rules, "brut")(stateSelector), missing = collectMissingVariables(analysis.targets) expect(analysis.targets[0].nodeValue).to.be.null expect(missing).to.have.key("brut") }) it("should handle inversions with missing variables", () => { let rawRules = dedent` - nom: net formule: multiplication: assiette: assiette variations: - si: cadre taux: 80% - si: ≠ cadre 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 = name => ({ net: 2000 }[name]), analysis = analyse(rules, "brut")(stateSelector), missing = collectMissingVariables(analysis.targets) expect(analysis.targets[0].nodeValue).to.be.null expect(missing).to.have.key("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 taux: 80% - si: ≠ cadre 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,["salaire brut","salaire total"])(stateSelector) let start = Date.now() let missing = collectMissingVariables(analysis.targets) let elapsed = Date.now()-start expect(elapsed).to.be.below(500) });